blob: 6a331d1c42fe8ed06fd471788fe33689d09a3e1b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200315 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200597 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
598 global.tune.sslprivatecache = 1;
599 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100600 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.sslcachesize = atol(args[1]);
607 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100608 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
609 unsigned int ssllifetime;
610 const char *res;
611
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617
618 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
619 if (res) {
620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
621 file, linenum, *res, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625
626 global.tune.ssllifetime = ssllifetime;
627 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100628 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.ssl_max_record = atol(args[1]);
635 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200636 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642 global.tune.ssl_default_dh_param = atol(args[1]);
643 if (global.tune.ssl_default_dh_param < 1024) {
644 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200649#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200650 else if (!strcmp(args[0], "tune.bufsize")) {
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.bufsize = atol(args[1]);
657 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
658 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100659 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100660 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200661 }
662 else if (!strcmp(args[0], "tune.maxrewrite")) {
663 if (*(args[1]) == 0) {
664 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT | ERR_FATAL;
666 goto out;
667 }
668 global.tune.maxrewrite = atol(args[1]);
669 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
670 global.tune.maxrewrite = global.tune.bufsize / 2;
671 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100672 else if (!strcmp(args[0], "tune.idletimer")) {
673 unsigned int idle;
674 const char *res;
675
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681
682 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
683 if (res) {
684 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
685 file, linenum, *res, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689
690 if (idle > 65535) {
691 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.idle_timer = idle;
696 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100697 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
698 if (global.tune.client_rcvbuf != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT;
701 goto out;
702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.client_rcvbuf = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
711 if (global.tune.server_rcvbuf != 0) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT;
714 goto out;
715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.tune.server_rcvbuf = atol(args[1]);
722 }
723 else if (!strcmp(args[0], "tune.sndbuf.client")) {
724 if (global.tune.client_sndbuf != 0) {
725 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
726 err_code |= ERR_ALERT;
727 goto out;
728 }
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734 global.tune.client_sndbuf = atol(args[1]);
735 }
736 else if (!strcmp(args[0], "tune.sndbuf.server")) {
737 if (global.tune.server_sndbuf != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT;
740 goto out;
741 }
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.server_sndbuf = atol(args[1]);
748 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200749 else if (!strcmp(args[0], "tune.pipesize")) {
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.pipesize = atol(args[1]);
756 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100757 else if (!strcmp(args[0], "tune.http.cookielen")) {
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
762 }
763 global.tune.cookie_len = atol(args[1]) + 1;
764 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200765 else if (!strcmp(args[0], "tune.http.maxhdr")) {
766 if (*(args[1]) == 0) {
767 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.max_http_hdr = atol(args[1]);
772 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100773 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
774#ifdef USE_ZLIB
775 if (*args[1]) {
776 global.tune.zlibmemlevel = atoi(args[1]);
777 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
778 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
779 file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 } else {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789#else
790 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
791 err_code |= ERR_ALERT | ERR_FATAL;
792 goto out;
793#endif
794 }
795 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
796#ifdef USE_ZLIB
797 if (*args[1]) {
798 global.tune.zlibwindowsize = atoi(args[1]);
799 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
800 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
801 file, linenum, args[0]);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 } else {
806 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
807 file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811#else
812 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815#endif
816 }
William Lallemandf3747832012-11-09 12:33:10 +0100817 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
818 if (*args[1]) {
819 global.tune.comp_maxlevel = atoi(args[1]);
820 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
821 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
822 file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 } else {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 else if (!strcmp(args[0], "uid")) {
834 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200835 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 err_code |= ERR_ALERT;
837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200843 }
844 global.uid = atol(args[1]);
845 }
846 else if (!strcmp(args[0], "gid")) {
847 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200848 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT;
850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 }
852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 }
857 global.gid = atol(args[1]);
858 }
Simon Horman98637e52014-06-20 12:30:16 +0900859 else if (!strcmp(args[0], "external-check")) {
860 global.external_check = 1;
861 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200862 /* user/group name handling */
863 else if (!strcmp(args[0], "user")) {
864 struct passwd *ha_user;
865 if (global.uid != 0) {
866 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200867 err_code |= ERR_ALERT;
868 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200869 }
870 errno = 0;
871 ha_user = getpwnam(args[1]);
872 if (ha_user != NULL) {
873 global.uid = (int)ha_user->pw_uid;
874 }
875 else {
876 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 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200878 }
879 }
880 else if (!strcmp(args[0], "group")) {
881 struct group *ha_group;
882 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200883 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT;
885 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200886 }
887 errno = 0;
888 ha_group = getgrnam(args[1]);
889 if (ha_group != NULL) {
890 global.gid = (int)ha_group->gr_gid;
891 }
892 else {
893 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 +0200894 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200895 }
896 }
897 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 }
904 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100905 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
906 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
907 file, linenum, args[0], LONGBITS, global.nbproc);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 }
912 else if (!strcmp(args[0], "maxconn")) {
913 if (global.maxconn != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 global.maxconn = atol(args[1]);
924#ifdef SYSTEM_MAXCONN
925 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
926 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);
927 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930#endif /* SYSTEM_MAXCONN */
931 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200932 else if (!strcmp(args[0], "maxsslconn")) {
933#ifdef USE_OPENSSL
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 global.maxsslconn = atol(args[1]);
940#else
Emeric Brun0914df82012-10-02 18:45:42 +0200941 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200944#endif
945 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100946 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
947#ifdef USE_OPENSSL
948 if (*(args[1]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 free(global.listen_default_ciphers);
954 global.listen_default_ciphers = strdup(args[1]);
955#else
956 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
959#endif
960 }
961 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
962#ifdef USE_OPENSSL
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
967 }
968 free(global.connect_default_ciphers);
969 global.connect_default_ciphers = strdup(args[1]);
970#else
971 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974#endif
975 }
Emeric Brun850efd52014-01-29 12:24:34 +0100976 else if (!strcmp(args[0], "ssl-server-verify")) {
977 if (*(args[1]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982 if (strcmp(args[1],"none") == 0)
983 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
984 else if (strcmp(args[1],"required") == 0)
985 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
986 else {
987 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200992 else if (!strcmp(args[0], "maxconnrate")) {
993 if (global.cps_lim != 0) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT;
996 goto out;
997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
1002 }
1003 global.cps_lim = atol(args[1]);
1004 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001005 else if (!strcmp(args[0], "maxsessrate")) {
1006 if (global.sps_lim != 0) {
1007 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT;
1009 goto out;
1010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015 }
1016 global.sps_lim = atol(args[1]);
1017 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001018 else if (!strcmp(args[0], "maxsslrate")) {
1019 if (global.ssl_lim != 0) {
1020 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1021 err_code |= ERR_ALERT;
1022 goto out;
1023 }
1024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 global.ssl_lim = atol(args[1]);
1030 }
William Lallemandd85f9172012-11-09 17:05:39 +01001031 else if (!strcmp(args[0], "maxcomprate")) {
1032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036 }
1037 global.comp_rate_lim = atoi(args[1]) * 1024;
1038 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001039 else if (!strcmp(args[0], "maxpipes")) {
1040 if (global.maxpipes != 0) {
1041 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT;
1043 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001044 }
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001049 }
1050 global.maxpipes = atol(args[1]);
1051 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001052 else if (!strcmp(args[0], "maxzlibmem")) {
1053 if (*(args[1]) == 0) {
1054 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
William Lallemande3a7d992012-11-20 11:25:20 +01001058 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001059 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001060 else if (!strcmp(args[0], "maxcompcpuusage")) {
1061 if (*(args[1]) == 0) {
1062 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001067 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001068 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
1071 }
1072}
1073
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 else if (!strcmp(args[0], "ulimit-n")) {
1075 if (global.rlimit_nofile != 0) {
1076 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT;
1078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 }
1080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
1085 global.rlimit_nofile = atol(args[1]);
1086 }
1087 else if (!strcmp(args[0], "chroot")) {
1088 if (global.chroot != NULL) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 global.chroot = strdup(args[1]);
1099 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001100 else if (!strcmp(args[0], "description")) {
1101 int i, len=0;
1102 char *d;
1103
1104 if (!*args[1]) {
1105 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1106 file, linenum, args[0]);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
1109 }
1110
Willy Tarreau348acfe2014-04-14 15:00:39 +02001111 for (i = 1; *args[i]; i++)
1112 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001113
1114 if (global.desc)
1115 free(global.desc);
1116
1117 global.desc = d = (char *)calloc(1, len);
1118
Willy Tarreau348acfe2014-04-14 15:00:39 +02001119 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1120 for (i = 2; *args[i]; i++)
1121 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001122 }
1123 else if (!strcmp(args[0], "node")) {
1124 int i;
1125 char c;
1126
1127 for (i=0; args[1][i]; i++) {
1128 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001129 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1130 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001131 break;
1132 }
1133
1134 if (!i || args[1][i]) {
1135 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1136 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1137 file, linenum, args[0]);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
1140 }
1141
1142 if (global.node)
1143 free(global.node);
1144
1145 global.node = strdup(args[1]);
1146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 else if (!strcmp(args[0], "pidfile")) {
1148 if (global.pidfile != NULL) {
1149 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001150 err_code |= ERR_ALERT;
1151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 }
1153 if (*(args[1]) == 0) {
1154 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 }
1158 global.pidfile = strdup(args[1]);
1159 }
Emeric Bruned760922010-10-22 17:59:25 +02001160 else if (!strcmp(args[0], "unix-bind")) {
1161 int cur_arg = 1;
1162 while (*(args[cur_arg])) {
1163 if (!strcmp(args[cur_arg], "prefix")) {
1164 if (global.unix_bind.prefix != NULL) {
1165 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1166 err_code |= ERR_ALERT;
1167 cur_arg += 2;
1168 continue;
1169 }
1170
1171 if (*(args[cur_arg+1]) == 0) {
1172 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1173 err_code |= ERR_ALERT | ERR_FATAL;
1174 goto out;
1175 }
1176 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1177 cur_arg += 2;
1178 continue;
1179 }
1180
1181 if (!strcmp(args[cur_arg], "mode")) {
1182
1183 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1184 cur_arg += 2;
1185 continue;
1186 }
1187
1188 if (!strcmp(args[cur_arg], "uid")) {
1189
1190 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1191 cur_arg += 2;
1192 continue;
1193 }
1194
1195 if (!strcmp(args[cur_arg], "gid")) {
1196
1197 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1198 cur_arg += 2;
1199 continue;
1200 }
1201
1202 if (!strcmp(args[cur_arg], "user")) {
1203 struct passwd *user;
1204
1205 user = getpwnam(args[cur_arg + 1]);
1206 if (!user) {
1207 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\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.uid = user->pw_uid;
1214 cur_arg += 2;
1215 continue;
1216 }
1217
1218 if (!strcmp(args[cur_arg], "group")) {
1219 struct group *group;
1220
1221 group = getgrnam(args[cur_arg + 1]);
1222 if (!group) {
1223 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1224 file, linenum, args[0], args[cur_arg + 1 ]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
1229 global.unix_bind.ux.gid = group->gr_gid;
1230 cur_arg += 2;
1231 continue;
1232 }
1233
Willy Tarreaub48f9582011-09-05 01:17:06 +02001234 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001235 file, linenum, args[0]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239 }
William Lallemand0f99e342011-10-12 17:50:54 +02001240 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1241 /* delete previous herited or defined syslog servers */
1242 struct logsrv *back;
1243 struct logsrv *tmp;
1244
1245 if (*(args[1]) != 0) {
1246 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250
1251 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1252 LIST_DEL(&tmp->list);
1253 free(tmp);
1254 }
1255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001257 struct sockaddr_storage *sk;
1258 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001259 struct logsrv *logsrv;
1260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (*(args[1]) == 0 || *(args[2]) == 0) {
1262 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
William Lallemand0f99e342011-10-12 17:50:54 +02001266
1267 logsrv = calloc(1, sizeof(struct logsrv));
1268
1269 logsrv->facility = get_log_facility(args[2]);
1270 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001273 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 }
1275
William Lallemand0f99e342011-10-12 17:50:54 +02001276 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001278 logsrv->level = get_log_level(args[3]);
1279 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001280 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001281 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001282 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 }
1284 }
1285
William Lallemand0f99e342011-10-12 17:50:54 +02001286 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001287 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001288 logsrv->minlvl = get_log_level(args[4]);
1289 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001290 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001292 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001293 }
1294 }
1295
Willy Tarreau902636f2013-03-10 19:44:48 +01001296 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001297 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001298 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001299 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001300 free(logsrv);
1301 goto out;
1302 }
1303 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001304
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001305 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001306 if (port1 != port2) {
1307 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1308 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001309 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001310 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001311 goto out;
1312 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001313
William Lallemand0f99e342011-10-12 17:50:54 +02001314 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001315 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001316 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318
William Lallemand0f99e342011-10-12 17:50:54 +02001319 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001320 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001321 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1322 char *name;
1323 int len;
1324
1325 if (global.log_send_hostname != NULL) {
1326 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT;
1328 goto out;
1329 }
1330
1331 if (*(args[1]))
1332 name = args[1];
1333 else
1334 name = hostname;
1335
1336 len = strlen(name);
1337
1338 /* We'll add a space after the name to respect the log format */
1339 free(global.log_send_hostname);
1340 global.log_send_hostname = malloc(len + 2);
1341 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1342 }
Kevinm48936af2010-12-22 16:08:21 +00001343 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1344 if (*(args[1]) == 0) {
1345 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
1348 }
1349 free(global.log_tag);
1350 global.log_tag = strdup(args[1]);
1351 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001352 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1353 if (global.spread_checks != 0) {
1354 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001355 err_code |= ERR_ALERT;
1356 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001357 }
1358 if (*(args[1]) == 0) {
1359 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001362 }
1363 global.spread_checks = atol(args[1]);
1364 if (global.spread_checks < 0 || global.spread_checks > 50) {
1365 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001369 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1370 const char *err;
1371 unsigned int val;
1372
1373
1374 if (*(args[1]) == 0) {
1375 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379
1380 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1381 if (err) {
1382 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1383 err_code |= ERR_ALERT | ERR_FATAL;
1384 }
1385 global.max_spread_checks = val;
1386 if (global.max_spread_checks < 0) {
1387 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1388 err_code |= ERR_ALERT | ERR_FATAL;
1389 }
1390 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001391 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1392#ifdef USE_CPU_AFFINITY
1393 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001394 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001395 unsigned long cpus = 0;
1396
1397 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001398 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001399 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001400 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001401 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001402 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001403 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001404 proc = atol(args[1]);
1405 if (proc >= 1 && proc <= LONGBITS)
1406 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001407 }
1408
1409 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001410 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",
1411 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415
1416 cur_arg = 2;
1417 while (*args[cur_arg]) {
1418 unsigned int low, high;
1419
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001420 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001421 char *dash = strchr(args[cur_arg], '-');
1422
1423 low = high = str2uic(args[cur_arg]);
1424 if (dash)
1425 high = str2uic(dash + 1);
1426
1427 if (high < low) {
1428 unsigned int swap = low;
1429 low = high;
1430 high = swap;
1431 }
1432
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001433 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001434 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001435 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
1440 while (low <= high)
1441 cpus |= 1UL << low++;
1442 }
1443 else {
1444 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1445 file, linenum, args[0], args[cur_arg]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 cur_arg++;
1450 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001451 for (i = 0; i < LONGBITS; i++)
1452 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001453 global.cpu_map[i] = cpus;
1454#else
1455 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1456 err_code |= ERR_ALERT | ERR_FATAL;
1457 goto out;
1458#endif
1459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001461 struct cfg_kw_list *kwl;
1462 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001463 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001464
1465 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1466 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1467 if (kwl->kw[index].section != CFG_GLOBAL)
1468 continue;
1469 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001470 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001471 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001472 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001474 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001475 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001476 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001477 err_code |= ERR_WARN;
1478 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001479 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001480 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001481 }
1482 }
1483 }
1484
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001486 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001488
Willy Tarreau058e9072009-07-20 09:30:05 +02001489 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001490 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001491 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492}
1493
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001494void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001496 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 defproxy.mode = PR_MODE_TCP;
1498 defproxy.state = PR_STNEW;
1499 defproxy.maxconn = cfg_maxpconn;
1500 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001501
Simon Horman66183002013-02-23 10:16:43 +09001502 defproxy.defsrv.check.inter = DEF_CHKINTR;
1503 defproxy.defsrv.check.fastinter = 0;
1504 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001505 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1506 defproxy.defsrv.agent.fastinter = 0;
1507 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001508 defproxy.defsrv.check.rise = DEF_RISETIME;
1509 defproxy.defsrv.check.fall = DEF_FALLTIME;
1510 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1511 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001512 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001513 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001514 defproxy.defsrv.maxqueue = 0;
1515 defproxy.defsrv.minconn = 0;
1516 defproxy.defsrv.maxconn = 0;
1517 defproxy.defsrv.slowstart = 0;
1518 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1519 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1520 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521}
1522
Willy Tarreauade5ec42010-01-28 19:33:49 +01001523
Willy Tarreau63af98d2014-05-18 08:11:41 +02001524/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1525 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1526 * ERR_FATAL in case of error.
1527 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001528static int create_cond_regex_rule(const char *file, int line,
1529 struct proxy *px, int dir, int action, int flags,
1530 const char *cmd, const char *reg, const char *repl,
1531 const char **cond_start)
1532{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001533 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001534 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001535 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001536 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001537 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001538 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001539 int cs;
1540 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001541
1542 if (px == &defproxy) {
1543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001544 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001545 goto err;
1546 }
1547
1548 if (*reg == 0) {
1549 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001550 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001551 goto err;
1552 }
1553
1554 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001555 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001556
Willy Tarreau5321c422010-01-28 20:35:13 +01001557 if (cond_start &&
1558 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001559 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1560 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1561 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001562 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001563 goto err;
1564 }
1565 }
1566 else if (cond_start && **cond_start) {
1567 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1568 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001569 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001570 goto err;
1571 }
1572
Willy Tarreau63af98d2014-05-18 08:11:41 +02001573 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001574 (dir == SMP_OPT_DIR_REQ) ?
1575 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1576 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1577 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001578
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001579 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001580 if (!preg) {
1581 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001582 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001583 goto err;
1584 }
1585
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001586 cs = !(flags & REG_ICASE);
1587 cap = !(flags & REG_NOSUB);
1588 error = NULL;
1589 if (!regex_comp(reg, preg, cs, cap, &error)) {
1590 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1591 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001592 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593 goto err;
1594 }
1595
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001596 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001597 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598 if (repl && err) {
1599 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1600 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001601 ret_code |= ERR_ALERT | ERR_FATAL;
1602 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001603 }
1604
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001605 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001606 ret_code |= ERR_WARN;
1607
1608 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001609
Willy Tarreau63af98d2014-05-18 08:11:41 +02001610 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001611 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001612 err:
1613 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001614 free(errmsg);
1615 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001616}
1617
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001620 * Returns the error code, 0 if OK, or any combination of :
1621 * - ERR_ABORT: must abort ASAP
1622 * - ERR_FATAL: we can continue parsing but not start the service
1623 * - ERR_WARN: a warning has been emitted
1624 * - ERR_ALERT: an alert has been emitted
1625 * Only the two first ones can stop processing, the two others are just
1626 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001628int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1629{
1630 static struct peers *curpeers = NULL;
1631 struct peer *newpeer = NULL;
1632 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001633 struct bind_conf *bind_conf;
1634 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001635 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001636 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001637
1638 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001639 if (!*args[1]) {
1640 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001641 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001642 goto out;
1643 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001644
1645 err = invalid_char(args[1]);
1646 if (err) {
1647 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1648 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001649 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001650 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001651 }
1652
1653 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1654 /*
1655 * If there are two proxies with the same name only following
1656 * combinations are allowed:
1657 */
1658 if (strcmp(curpeers->id, args[1]) == 0) {
1659 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1660 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1661 err_code |= ERR_WARN;
1662 }
1663 }
1664
1665 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1666 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1667 err_code |= ERR_ALERT | ERR_ABORT;
1668 goto out;
1669 }
1670
1671 curpeers->next = peers;
1672 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001673 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001674 curpeers->conf.line = linenum;
1675 curpeers->last_change = now.tv_sec;
1676 curpeers->id = strdup(args[1]);
1677 }
1678 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001679 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001680 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001681 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001682
1683 if (!*args[2]) {
1684 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1685 file, linenum, args[0]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
1690 err = invalid_char(args[1]);
1691 if (err) {
1692 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1693 file, linenum, *err, args[1]);
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
1696 }
1697
1698 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1699 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1700 err_code |= ERR_ALERT | ERR_ABORT;
1701 goto out;
1702 }
1703
1704 /* the peers are linked backwards first */
1705 curpeers->count++;
1706 newpeer->next = curpeers->remote;
1707 curpeers->remote = newpeer;
1708 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001709 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001710 newpeer->conf.line = linenum;
1711
1712 newpeer->last_change = now.tv_sec;
1713 newpeer->id = strdup(args[1]);
1714
Willy Tarreau902636f2013-03-10 19:44:48 +01001715 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001716 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001717 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001720 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001721
1722 proto = protocol_by_family(sk->ss_family);
1723 if (!proto || !proto->connect) {
1724 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1725 file, linenum, args[0], args[1]);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001729
1730 if (port1 != port2) {
1731 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1732 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
1735 }
1736
Willy Tarreau2aa38802013-02-20 19:20:59 +01001737 if (!port1) {
1738 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1739 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
1742 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001743
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001745 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001746 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001747 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001748
Emeric Brun32da3c42010-09-23 18:39:19 +02001749 if (strcmp(newpeer->id, localpeer) == 0) {
1750 /* Current is local peer, it define a frontend */
1751 newpeer->local = 1;
1752
1753 if (!curpeers->peers_fe) {
1754 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1755 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1756 err_code |= ERR_ALERT | ERR_ABORT;
1757 goto out;
1758 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001759
Willy Tarreau237250c2011-07-29 01:49:03 +02001760 init_new_proxy(curpeers->peers_fe);
1761 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001762
1763 curpeers->peers_fe->last_change = now.tv_sec;
1764 curpeers->peers_fe->id = strdup(args[1]);
1765 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001766 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001767 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1768 curpeers->peers_fe->timeout.connect = 5000;
1769 curpeers->peers_fe->accept = peer_accept;
1770 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001771 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1772 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001773
1774 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1775
Willy Tarreau902636f2013-03-10 19:44:48 +01001776 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1777 if (errmsg && *errmsg) {
1778 indent_msg(&errmsg, 2);
1779 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001780 }
1781 else
1782 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1783 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001784 err_code |= ERR_FATAL;
1785 goto out;
1786 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001787
1788 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001789 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001790 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1791 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1792 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1793 l->accept = session_accept;
1794 l->handler = process_session;
1795 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1796 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1797 global.maxsock += l->maxconn;
1798 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001799 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001800 else {
1801 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1802 file, linenum, args[0], args[1],
1803 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1804 err_code |= ERR_FATAL;
1805 goto out;
1806 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001807 }
1808 } /* neither "peer" nor "peers" */
1809 else if (*args[0] != 0) {
1810 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814
1815out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001816 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001817 return err_code;
1818}
1819
Willy Tarreau3842f002009-06-14 11:39:52 +02001820int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821{
1822 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001823 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001824 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001825 int rc;
1826 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001827 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001828 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001829 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001830 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001831 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 if (!strcmp(args[0], "listen"))
1834 rc = PR_CAP_LISTEN;
1835 else if (!strcmp(args[0], "frontend"))
1836 rc = PR_CAP_FE | PR_CAP_RS;
1837 else if (!strcmp(args[0], "backend"))
1838 rc = PR_CAP_BE | PR_CAP_RS;
1839 else if (!strcmp(args[0], "ruleset"))
1840 rc = PR_CAP_RS;
1841 else
1842 rc = PR_CAP_NONE;
1843
1844 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001845 struct ebpt_node *node;
1846
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847 if (!*args[1]) {
1848 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1849 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_ALERT | ERR_ABORT;
1852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001854
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001855 err = invalid_char(args[1]);
1856 if (err) {
1857 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1858 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001860 }
1861
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001862 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1863 curproxy = container_of(node, struct proxy, conf.by_name);
1864
1865 if (strcmp(curproxy->id, args[1]) != 0)
1866 break;
1867
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001868 /*
1869 * If there are two proxies with the same name only following
1870 * combinations are allowed:
1871 *
1872 * listen backend frontend ruleset
1873 * listen - - - -
1874 * backend - - OK -
1875 * frontend - OK - -
1876 * ruleset - - - -
1877 */
1878
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001879 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1880 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001881 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1882 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1883 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001884 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001885 }
1886 }
1887
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1889 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_ALERT | ERR_ABORT;
1891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001893
Willy Tarreau97cb7802010-01-03 20:23:58 +01001894 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 curproxy->next = proxy;
1896 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001897 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1898 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001899 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001902 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903
1904 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001906 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001907
Willy Tarreau4348fad2012-09-20 16:48:07 +02001908 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1909
Willy Tarreau902636f2013-03-10 19:44:48 +01001910 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1911 if (errmsg && *errmsg) {
1912 indent_msg(&errmsg, 2);
1913 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001914 }
1915 else
1916 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1917 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001918 err_code |= ERR_FATAL;
1919 goto out;
1920 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001921
Willy Tarreau4348fad2012-09-20 16:48:07 +02001922 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001923 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 }
1926
1927 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001928 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001929 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001930
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001933 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001934 curproxy->no_options = defproxy.no_options;
1935 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001936 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001937 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001938 curproxy->except_net = defproxy.except_net;
1939 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001940 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001941 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001943 if (defproxy.fwdfor_hdr_len) {
1944 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1945 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1946 }
1947
Willy Tarreaub86db342009-11-30 11:50:16 +01001948 if (defproxy.orgto_hdr_len) {
1949 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1950 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1951 }
1952
Mark Lamourinec2247f02012-01-04 13:02:01 -05001953 if (defproxy.server_id_hdr_len) {
1954 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1955 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1956 }
1957
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (curproxy->cap & PR_CAP_FE) {
1959 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001960 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001961 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001962
1963 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001964 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1965 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001966
1967 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969
Willy Tarreau977b8e42006-12-29 14:19:17 +01001970 if (curproxy->cap & PR_CAP_BE) {
1971 curproxy->fullconn = defproxy.fullconn;
1972 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001973 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001975 if (defproxy.check_req) {
1976 curproxy->check_req = calloc(1, defproxy.check_len);
1977 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1978 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001979 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001981 if (defproxy.expect_str) {
1982 curproxy->expect_str = strdup(defproxy.expect_str);
1983 if (defproxy.expect_regex) {
1984 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001985 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
1986 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001987 }
1988 }
1989
Willy Tarreau67402132012-05-31 20:40:20 +02001990 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991 if (defproxy.cookie_name)
1992 curproxy->cookie_name = strdup(defproxy.cookie_name);
1993 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001994 if (defproxy.cookie_domain)
1995 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001996
Willy Tarreau31936852010-10-06 16:59:56 +02001997 if (defproxy.cookie_maxidle)
1998 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1999
2000 if (defproxy.cookie_maxlife)
2001 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2002
Emeric Brun647caf12009-06-30 17:57:00 +02002003 if (defproxy.rdp_cookie_name)
2004 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2005 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2006
Willy Tarreau01732802007-11-01 22:48:15 +01002007 if (defproxy.url_param_name)
2008 curproxy->url_param_name = strdup(defproxy.url_param_name);
2009 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002010
Benoitaffb4812009-03-25 13:02:10 +01002011 if (defproxy.hh_name)
2012 curproxy->hh_name = strdup(defproxy.hh_name);
2013 curproxy->hh_len = defproxy.hh_len;
2014 curproxy->hh_match_domain = defproxy.hh_match_domain;
2015
Willy Tarreauef9a3602012-12-08 22:29:20 +01002016 if (defproxy.conn_src.iface_name)
2017 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2018 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002019 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002020#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002021 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002022#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002025 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002026 if (defproxy.capture_name)
2027 curproxy->capture_name = strdup(defproxy.capture_name);
2028 curproxy->capture_namelen = defproxy.capture_namelen;
2029 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031
Willy Tarreau977b8e42006-12-29 14:19:17 +01002032 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002033 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002034 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002035 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002036 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002037 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038 curproxy->mon_net = defproxy.mon_net;
2039 curproxy->mon_mask = defproxy.mon_mask;
2040 if (defproxy.monitor_uri)
2041 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2042 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002043 if (defproxy.defbe.name)
2044 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002045
2046 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002047 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2048 if (curproxy->conf.logformat_string &&
2049 curproxy->conf.logformat_string != default_http_log_format &&
2050 curproxy->conf.logformat_string != default_tcp_log_format &&
2051 curproxy->conf.logformat_string != clf_http_log_format)
2052 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2053
2054 if (defproxy.conf.lfs_file) {
2055 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2056 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002058 }
2059
2060 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002061 curproxy->timeout.connect = defproxy.timeout.connect;
2062 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002063 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002064 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002065 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002066 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002067 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002068 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002069 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002070 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 }
2072
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002074 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002075
2076 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002077 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002078 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002079 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002080 LIST_INIT(&node->list);
2081 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2082 }
2083
Willy Tarreau62a61232013-04-12 18:13:46 +02002084 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2085 if (curproxy->conf.uniqueid_format_string)
2086 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2087
2088 if (defproxy.conf.uif_file) {
2089 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2090 curproxy->conf.uif_line = defproxy.conf.uif_line;
2091 }
William Lallemanda73203e2012-03-12 12:48:57 +01002092
2093 /* copy default header unique id */
2094 if (defproxy.header_unique_id)
2095 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2096
William Lallemand82fe75c2012-10-23 10:25:10 +02002097 /* default compression options */
2098 if (defproxy.comp != NULL) {
2099 curproxy->comp = calloc(1, sizeof(struct comp));
2100 curproxy->comp->algos = defproxy.comp->algos;
2101 curproxy->comp->types = defproxy.comp->types;
2102 }
2103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002105 curproxy->conf.used_listener_id = EB_ROOT;
2106 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002107
Simon Horman98637e52014-06-20 12:30:16 +09002108 if (defproxy.check_path)
2109 curproxy->check_path = strdup(defproxy.check_path);
2110 if (defproxy.check_command)
2111 curproxy->check_command = strdup(defproxy.check_command);
2112
Willy Tarreau93893792009-07-23 13:19:11 +02002113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 }
2115 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2116 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002117 /* FIXME-20070101: we should do this too at the end of the
2118 * config parsing to free all default values.
2119 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002120 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002121 free(defproxy.check_command);
2122 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002123 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002124 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002125 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002126 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002127 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002128 free(defproxy.capture_name);
2129 free(defproxy.monitor_uri);
2130 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002131 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002132 free(defproxy.fwdfor_hdr_name);
2133 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002134 free(defproxy.orgto_hdr_name);
2135 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002136 free(defproxy.server_id_hdr_name);
2137 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002138 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002139 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002140 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002141 free(defproxy.expect_regex);
2142 defproxy.expect_regex = NULL;
2143 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002144
Willy Tarreau62a61232013-04-12 18:13:46 +02002145 if (defproxy.conf.logformat_string != default_http_log_format &&
2146 defproxy.conf.logformat_string != default_tcp_log_format &&
2147 defproxy.conf.logformat_string != clf_http_log_format)
2148 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002149
Willy Tarreau62a61232013-04-12 18:13:46 +02002150 free(defproxy.conf.uniqueid_format_string);
2151 free(defproxy.conf.lfs_file);
2152 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002153
Willy Tarreaua534fea2008-08-03 12:19:50 +02002154 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002155 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002156
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 /* we cannot free uri_auth because it might already be used */
2158 init_default_instance();
2159 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002160 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2161 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002162 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
2165 else if (curproxy == NULL) {
2166 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002170
2171 /* update the current file and line being parsed */
2172 curproxy->conf.args.file = curproxy->conf.file;
2173 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174
2175 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002176 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2177 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2178 if (err_code & ERR_FATAL)
2179 goto out;
2180 }
2181 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002182 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002183 int cur_arg;
2184
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 if (curproxy == &defproxy) {
2186 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002190 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192
Willy Tarreau24709282013-03-10 21:32:12 +01002193 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002194 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002199
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002200 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002201
2202 /* use default settings for unix sockets */
2203 bind_conf->ux.uid = global.unix_bind.ux.uid;
2204 bind_conf->ux.gid = global.unix_bind.ux.gid;
2205 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002206
2207 /* NOTE: the following line might create several listeners if there
2208 * are comma-separated IPs or port ranges. So all further processing
2209 * will have to be applied to all listeners created after last_listen.
2210 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002211 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2212 if (errmsg && *errmsg) {
2213 indent_msg(&errmsg, 2);
2214 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002215 }
2216 else
2217 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2218 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002222
Willy Tarreau4348fad2012-09-20 16:48:07 +02002223 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2224 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002225 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002226 }
2227
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002228 cur_arg = 2;
2229 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002230 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002231 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002232 char *err;
2233
Willy Tarreau26982662012-09-12 23:17:10 +02002234 kw = bind_find_kw(args[cur_arg]);
2235 if (kw) {
2236 char *err = NULL;
2237 int code;
2238
2239 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002240 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2241 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002242 cur_arg += 1 + kw->skip ;
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246
Willy Tarreau4348fad2012-09-20 16:48:07 +02002247 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002248 err_code |= code;
2249
2250 if (code) {
2251 if (err && *err) {
2252 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002253 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002254 }
2255 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002256 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2257 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002258 if (code & ERR_FATAL) {
2259 free(err);
2260 cur_arg += 1 + kw->skip;
2261 goto out;
2262 }
2263 }
2264 free(err);
2265 cur_arg += 1 + kw->skip;
2266 continue;
2267 }
2268
Willy Tarreau8638f482012-09-18 18:01:17 +02002269 err = NULL;
2270 if (!bind_dumped) {
2271 bind_dump_kws(&err);
2272 indent_msg(&err, 4);
2273 bind_dumped = 1;
2274 }
2275
2276 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2277 file, linenum, args[0], args[1], args[cur_arg],
2278 err ? " Registered keywords :" : "", err ? err : "");
2279 free(err);
2280
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002283 }
Willy Tarreau93893792009-07-23 13:19:11 +02002284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002287 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 /* flush useless bits */
2297 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002300 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002301 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303
Willy Tarreau1c47f852006-07-09 08:22:27 +02002304 if (!*args[1]) {
2305 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002309 }
2310
Willy Tarreaua534fea2008-08-03 12:19:50 +02002311 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002312 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002313 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002314 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002315 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2316
Willy Tarreau93893792009-07-23 13:19:11 +02002317 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2320 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2321 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2322 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2323 else {
2324 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 }
2328 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002329 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002330 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002331
2332 if (curproxy == &defproxy) {
2333 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2334 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002337 }
2338
2339 if (!*args[1]) {
2340 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002344 }
2345
2346 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002347 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002348
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002349 if (curproxy->uuid <= 0) {
2350 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002354 }
2355
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002356 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2357 if (node) {
2358 struct proxy *target = container_of(node, struct proxy, conf.id);
2359 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2360 file, linenum, proxy_type_str(curproxy), curproxy->id,
2361 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002366 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002367 else if (!strcmp(args[0], "description")) {
2368 int i, len=0;
2369 char *d;
2370
Cyril Bonté99ed3272010-01-24 23:29:44 +01002371 if (curproxy == &defproxy) {
2372 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2373 file, linenum, args[0]);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
2376 }
2377
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002378 if (!*args[1]) {
2379 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2380 file, linenum, args[0]);
2381 return -1;
2382 }
2383
Willy Tarreau348acfe2014-04-14 15:00:39 +02002384 for (i = 1; *args[i]; i++)
2385 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002386
2387 d = (char *)calloc(1, len);
2388 curproxy->desc = d;
2389
Willy Tarreau348acfe2014-04-14 15:00:39 +02002390 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2391 for (i = 2; *args[i]; i++)
2392 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002393
2394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2396 curproxy->state = PR_STSTOPPED;
2397 }
2398 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2399 curproxy->state = PR_STNEW;
2400 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002401 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2402 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002403 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002404
2405 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002406 unsigned int low, high;
2407
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002408 if (strcmp(args[cur_arg], "all") == 0) {
2409 set = 0;
2410 break;
2411 }
2412 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002413 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002414 }
2415 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002416 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002417 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002418 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002419 char *dash = strchr(args[cur_arg], '-');
2420
2421 low = high = str2uic(args[cur_arg]);
2422 if (dash)
2423 high = str2uic(dash + 1);
2424
2425 if (high < low) {
2426 unsigned int swap = low;
2427 low = high;
2428 high = swap;
2429 }
2430
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002431 if (low < 1 || high > LONGBITS) {
2432 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2433 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002436 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002437 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002438 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002439 }
2440 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002441 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2442 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002445 }
2446 cur_arg++;
2447 }
2448 curproxy->bind_proc = set;
2449 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002450 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002451 if (curproxy == &defproxy) {
2452 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002455 }
2456
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002457 err = invalid_char(args[1]);
2458 if (err) {
2459 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2460 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002462 }
2463
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002464 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002465 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2466 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002469 }
2470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2472 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473
Willy Tarreau977b8e42006-12-29 14:19:17 +01002474 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 if (*(args[1]) == 0) {
2478 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2479 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002483
Willy Tarreau67402132012-05-31 20:40:20 +02002484 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002485 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002486 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002487 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 curproxy->cookie_name = strdup(args[1]);
2489 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002490
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 cur_arg = 2;
2492 while (*(args[cur_arg])) {
2493 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002494 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
2496 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002497 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 }
2499 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002500 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
2502 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002503 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 }
2505 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002506 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002508 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002509 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002512 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002514 else if (!strcmp(args[cur_arg], "httponly")) {
2515 curproxy->ck_opts |= PR_CK_HTTPONLY;
2516 }
2517 else if (!strcmp(args[cur_arg], "secure")) {
2518 curproxy->ck_opts |= PR_CK_SECURE;
2519 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002520 else if (!strcmp(args[cur_arg], "domain")) {
2521 if (!*args[cur_arg + 1]) {
2522 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2523 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002526 }
2527
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002528 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002529 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002530 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2531 " dots nor does not start with a dot."
2532 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002533 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002534 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002535 }
2536
2537 err = invalid_domainchar(args[cur_arg + 1]);
2538 if (err) {
2539 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2540 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002543 }
2544
Willy Tarreau68a897b2009-12-03 23:28:34 +01002545 if (!curproxy->cookie_domain) {
2546 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2547 } else {
2548 /* one domain was already specified, add another one by
2549 * building the string which will be returned along with
2550 * the cookie.
2551 */
2552 char *new_ptr;
2553 int new_len = strlen(curproxy->cookie_domain) +
2554 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2555 new_ptr = malloc(new_len);
2556 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2557 free(curproxy->cookie_domain);
2558 curproxy->cookie_domain = new_ptr;
2559 }
Willy Tarreau31936852010-10-06 16:59:56 +02002560 cur_arg++;
2561 }
2562 else if (!strcmp(args[cur_arg], "maxidle")) {
2563 unsigned int maxidle;
2564 const char *res;
2565
2566 if (!*args[cur_arg + 1]) {
2567 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2568 file, linenum, args[cur_arg]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
2572
2573 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2574 if (res) {
2575 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2576 file, linenum, *res, args[cur_arg]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
2580 curproxy->cookie_maxidle = maxidle;
2581 cur_arg++;
2582 }
2583 else if (!strcmp(args[cur_arg], "maxlife")) {
2584 unsigned int maxlife;
2585 const char *res;
2586
2587 if (!*args[cur_arg + 1]) {
2588 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2589 file, linenum, args[cur_arg]);
2590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
2592 }
2593
2594 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2595 if (res) {
2596 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2597 file, linenum, *res, args[cur_arg]);
2598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
2600 }
2601 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002602 cur_arg++;
2603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002605 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 +02002606 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
2610 cur_arg++;
2611 }
Willy Tarreau67402132012-05-31 20:40:20 +02002612 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2614 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
2617
Willy Tarreau67402132012-05-31 20:40:20 +02002618 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2620 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002623
Willy Tarreau67402132012-05-31 20:40:20 +02002624 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002625 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2626 file, linenum);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002630 else if (!strcmp(args[0], "external-check")) {
2631 if (*(args[1]) == 0) {
2632 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2633 file, linenum, args[0]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637
2638 if (!strcmp(args[1], "command")) {
2639 if (*(args[1]) == 0) {
2640 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2641 file, linenum, args[1]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645 free(curproxy->check_command);
2646 curproxy->check_command = strdup(args[2]);
2647 }
2648 else if (!strcmp(args[1], "path")) {
2649 if (*(args[1]) == 0) {
2650 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2651 file, linenum, args[1]);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655 free(curproxy->check_path);
2656 curproxy->check_path = strdup(args[2]);
2657 }
2658 else {
2659 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2660 file, linenum, args[1]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002665 else if (!strcmp(args[0], "persist")) { /* persist */
2666 if (*(args[1]) == 0) {
2667 Alert("parsing [%s:%d] : missing persist method.\n",
2668 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002671 }
2672
2673 if (!strncmp(args[1], "rdp-cookie", 10)) {
2674 curproxy->options2 |= PR_O2_RDPC_PRST;
2675
Emeric Brunb982a3d2010-01-04 15:45:53 +01002676 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002677 const char *beg, *end;
2678
2679 beg = args[1] + 11;
2680 end = strchr(beg, ')');
2681
2682 if (!end || end == beg) {
2683 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2684 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002687 }
2688
2689 free(curproxy->rdp_cookie_name);
2690 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2691 curproxy->rdp_cookie_len = end-beg;
2692 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002693 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002694 free(curproxy->rdp_cookie_name);
2695 curproxy->rdp_cookie_name = strdup("msts");
2696 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2697 }
2698 else { /* syntax */
2699 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2700 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002703 }
2704 }
2705 else {
2706 Alert("parsing [%s:%d] : unknown persist method.\n",
2707 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002710 }
2711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002713 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002715 if (curproxy == &defproxy) {
2716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002725 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 }
2730 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002731 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 curproxy->appsession_name = strdup(args[1]);
2733 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2734 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002735 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2736 if (err) {
2737 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2738 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002741 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002742 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002743
Willy Tarreau51041c72007-09-09 21:56:53 +02002744 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2745 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_ALERT | ERR_ABORT;
2747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002749
2750 cur_arg = 6;
2751 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002752 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2753 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002754 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002755 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002756 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002757 } else if (!strcmp(args[cur_arg], "prefix")) {
2758 curproxy->options2 |= PR_O2_AS_PFX;
2759 } else if (!strcmp(args[cur_arg], "mode")) {
2760 if (!*args[cur_arg + 1]) {
2761 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2762 file, linenum, args[0], args[cur_arg]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766
2767 cur_arg++;
2768 if (!strcmp(args[cur_arg], "query-string")) {
2769 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2770 curproxy->options2 |= PR_O2_AS_M_QS;
2771 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2772 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2773 curproxy->options2 |= PR_O2_AS_M_PP;
2774 } else {
2775 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
2778 }
2779 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002780 cur_arg++;
2781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 } /* Url App Session */
2783 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002784 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002788 if (curproxy == &defproxy) {
2789 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 if (*(args[4]) == 0) {
2795 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2796 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002799 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002800 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801 curproxy->capture_name = strdup(args[2]);
2802 curproxy->capture_namelen = strlen(curproxy->capture_name);
2803 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 curproxy->to_log |= LW_COOKIE;
2805 }
2806 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2807 struct cap_hdr *hdr;
2808
2809 if (curproxy == &defproxy) {
2810 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 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002813 }
2814
2815 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2816 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2817 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 }
2821
2822 hdr = calloc(sizeof(struct cap_hdr), 1);
2823 hdr->next = curproxy->req_cap;
2824 hdr->name = strdup(args[3]);
2825 hdr->namelen = strlen(args[3]);
2826 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002827 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 hdr->index = curproxy->nb_req_cap++;
2829 curproxy->req_cap = hdr;
2830 curproxy->to_log |= LW_REQHDR;
2831 }
2832 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2833 struct cap_hdr *hdr;
2834
2835 if (curproxy == &defproxy) {
2836 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 +02002837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
2840
2841 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2842 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2843 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
2847 hdr = calloc(sizeof(struct cap_hdr), 1);
2848 hdr->next = curproxy->rsp_cap;
2849 hdr->name = strdup(args[3]);
2850 hdr->namelen = strlen(args[3]);
2851 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002852 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 hdr->index = curproxy->nb_rsp_cap++;
2854 curproxy->rsp_cap = hdr;
2855 curproxy->to_log |= LW_RSPHDR;
2856 }
2857 else {
2858 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
2863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002866 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 if (*(args[1]) == 0) {
2869 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
2874 curproxy->conn_retries = atol(args[1]);
2875 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002876 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002877 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002878
2879 if (curproxy == &defproxy) {
2880 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
2883 }
2884
Willy Tarreau20b0de52012-12-24 15:45:22 +01002885 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2886 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2887 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2888 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002889 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002890 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2891 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 +01002892 file, linenum, args[0]);
2893 err_code |= ERR_WARN;
2894 }
2895
Willy Tarreauff011f22011-01-06 17:51:27 +01002896 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002897
Willy Tarreauff011f22011-01-06 17:51:27 +01002898 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002899 err_code |= ERR_ALERT | ERR_ABORT;
2900 goto out;
2901 }
2902
Willy Tarreau5002f572014-04-23 01:32:02 +02002903 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002904 err_code |= warnif_cond_conflicts(rule->cond,
2905 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2906 file, linenum);
2907
Willy Tarreauff011f22011-01-06 17:51:27 +01002908 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002909 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002910 else if (!strcmp(args[0], "http-response")) { /* response access control */
2911 struct http_res_rule *rule;
2912
2913 if (curproxy == &defproxy) {
2914 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917 }
2918
2919 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2920 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2921 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2922 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2923 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2924 file, linenum, args[0]);
2925 err_code |= ERR_WARN;
2926 }
2927
2928 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2929
2930 if (!rule) {
2931 err_code |= ERR_ALERT | ERR_ABORT;
2932 goto out;
2933 }
2934
2935 err_code |= warnif_cond_conflicts(rule->cond,
2936 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2937 file, linenum);
2938
2939 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2940 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002941 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2942 /* set the header name and length into the proxy structure */
2943 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2944 err_code |= ERR_WARN;
2945
2946 if (!*args[1]) {
2947 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2948 file, linenum, args[0]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
2953 /* set the desired header name */
2954 free(curproxy->server_id_hdr_name);
2955 curproxy->server_id_hdr_name = strdup(args[1]);
2956 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2957 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002958 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002959 struct http_req_rule *rule;
2960
Willy Tarreaub099aca2008-10-12 17:26:37 +02002961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002965 }
2966
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002967 /* emulate "block" using "http-request block". Since these rules are supposed to
2968 * be processed before all http-request rules, we put them into their own list
2969 * and will insert them at the end.
2970 */
2971 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2972 if (!rule) {
2973 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002974 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002975 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002976 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2977 err_code |= warnif_cond_conflicts(rule->cond,
2978 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2979 file, linenum);
2980 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002981
2982 if (!already_warned(WARN_BLOCK_DEPRECATED))
2983 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]);
2984
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002985 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002986 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002987 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002988
Cyril Bonté99ed3272010-01-24 23:29:44 +01002989 if (curproxy == &defproxy) {
2990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002995 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002996 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2997 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003000 }
3001
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003002 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003003 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003004 err_code |= warnif_cond_conflicts(rule->cond,
3005 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3006 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003007 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003008 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003009 struct switching_rule *rule;
3010
Willy Tarreaub099aca2008-10-12 17:26:37 +02003011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003015 }
3016
Willy Tarreau55ea7572007-06-17 19:56:27 +02003017 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003019
3020 if (*(args[1]) == 0) {
3021 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003024 }
3025
Willy Tarreauf51658d2014-04-23 01:21:56 +02003026 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3027 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3028 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3029 file, linenum, errmsg);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003033
Willy Tarreauf51658d2014-04-23 01:21:56 +02003034 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003035 }
3036
3037 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3038 rule->cond = cond;
3039 rule->be.name = strdup(args[1]);
3040 LIST_INIT(&rule->list);
3041 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3042 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003043 else if (strcmp(args[0], "use-server") == 0) {
3044 struct server_rule *rule;
3045
3046 if (curproxy == &defproxy) {
3047 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
3051
3052 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3053 err_code |= ERR_WARN;
3054
3055 if (*(args[1]) == 0) {
3056 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060
3061 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3062 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3063 file, linenum, args[0]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003068 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3069 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3070 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003075 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003076
3077 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3078 rule->cond = cond;
3079 rule->srv.name = strdup(args[1]);
3080 LIST_INIT(&rule->list);
3081 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3082 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3083 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003084 else if ((!strcmp(args[0], "force-persist")) ||
3085 (!strcmp(args[0], "ignore-persist"))) {
3086 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003087
3088 if (curproxy == &defproxy) {
3089 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093
3094 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3095 err_code |= ERR_WARN;
3096
Willy Tarreauef6494c2010-01-28 17:12:36 +01003097 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003098 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3099 file, linenum, args[0]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003104 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3105 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3106 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003111 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3112 * where force-persist is applied.
3113 */
3114 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003115
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003116 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003117 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003118 if (!strcmp(args[0], "force-persist")) {
3119 rule->type = PERSIST_TYPE_FORCE;
3120 } else {
3121 rule->type = PERSIST_TYPE_IGNORE;
3122 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003123 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003124 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003125 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 else if (!strcmp(args[0], "stick-table")) {
3127 int myidx = 1;
3128
Emeric Brun32da3c42010-09-23 18:39:19 +02003129 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003130 curproxy->table.type = (unsigned int)-1;
3131 while (*args[myidx]) {
3132 const char *err;
3133
3134 if (strcmp(args[myidx], "size") == 0) {
3135 myidx++;
3136 if (!*(args[myidx])) {
3137 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3138 file, linenum, args[myidx-1]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
3142 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3143 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3144 file, linenum, *err, args[myidx-1]);
3145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
3147 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003148 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003150 else if (strcmp(args[myidx], "peers") == 0) {
3151 myidx++;
Godbach50523162013-12-11 19:48:57 +08003152 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003153 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3154 file, linenum, args[myidx-1]);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Godbach50523162013-12-11 19:48:57 +08003157 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003158 curproxy->table.peers.name = strdup(args[myidx++]);
3159 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 else if (strcmp(args[myidx], "expire") == 0) {
3161 myidx++;
3162 if (!*(args[myidx])) {
3163 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3164 file, linenum, args[myidx-1]);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3169 if (err) {
3170 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3171 file, linenum, *err, args[myidx-1]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
3175 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003176 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003177 }
3178 else if (strcmp(args[myidx], "nopurge") == 0) {
3179 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003180 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 }
3182 else if (strcmp(args[myidx], "type") == 0) {
3183 myidx++;
3184 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3185 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3186 file, linenum, args[myidx]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003190 /* myidx already points to next arg */
3191 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003192 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003193 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003194 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003195
3196 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003197 nw = args[myidx];
3198 while (*nw) {
3199 /* the "store" keyword supports a comma-separated list */
3200 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003201 sa = NULL; /* store arg */
3202 while (*nw && *nw != ',') {
3203 if (*nw == '(') {
3204 *nw = 0;
3205 sa = ++nw;
3206 while (*nw != ')') {
3207 if (!*nw) {
3208 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3209 file, linenum, args[0], cw);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213 nw++;
3214 }
3215 *nw = '\0';
3216 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003217 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003218 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003219 if (*nw)
3220 *nw++ = '\0';
3221 type = stktable_get_data_type(cw);
3222 if (type < 0) {
3223 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3224 file, linenum, args[0], cw);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
Willy Tarreauac782882010-06-20 10:41:54 +02003228
3229 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3230 switch (err) {
3231 case PE_NONE: break;
3232 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003233 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3234 file, linenum, args[0], cw);
3235 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003236 break;
3237
3238 case PE_ARG_MISSING:
3239 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3240 file, linenum, args[0], cw);
3241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
3243
3244 case PE_ARG_NOT_USED:
3245 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3246 file, linenum, args[0], cw);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249
3250 default:
3251 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3252 file, linenum, args[0], cw);
3253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003255 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003256 }
3257 myidx++;
3258 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003259 else {
3260 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3261 file, linenum, args[myidx]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003265 }
3266
3267 if (!curproxy->table.size) {
3268 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3269 file, linenum);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
3273
3274 if (curproxy->table.type == (unsigned int)-1) {
3275 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3276 file, linenum);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280 }
3281 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003282 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003283 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003284 int myidx = 0;
3285 const char *name = NULL;
3286 int flags;
3287
3288 if (curproxy == &defproxy) {
3289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293
3294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3295 err_code |= ERR_WARN;
3296 goto out;
3297 }
3298
3299 myidx++;
3300 if ((strcmp(args[myidx], "store") == 0) ||
3301 (strcmp(args[myidx], "store-request") == 0)) {
3302 myidx++;
3303 flags = STK_IS_STORE;
3304 }
3305 else if (strcmp(args[myidx], "store-response") == 0) {
3306 myidx++;
3307 flags = STK_IS_STORE | STK_ON_RSP;
3308 }
3309 else if (strcmp(args[myidx], "match") == 0) {
3310 myidx++;
3311 flags = STK_IS_MATCH;
3312 }
3313 else if (strcmp(args[myidx], "on") == 0) {
3314 myidx++;
3315 flags = STK_IS_MATCH | STK_IS_STORE;
3316 }
3317 else {
3318 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
3322
3323 if (*(args[myidx]) == 0) {
3324 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003329 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003330 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003331 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003332 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
3336
3337 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003338 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3339 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3340 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003341 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003342 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003343 goto out;
3344 }
3345 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003346 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3347 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3348 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003349 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003350 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003351 goto out;
3352 }
3353 }
3354
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003355 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003356 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003357
Emeric Brunb982a3d2010-01-04 15:45:53 +01003358 if (strcmp(args[myidx], "table") == 0) {
3359 myidx++;
3360 name = args[myidx++];
3361 }
3362
Willy Tarreauef6494c2010-01-28 17:12:36 +01003363 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003364 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3365 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3366 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003368 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003369 goto out;
3370 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003371 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003372 else if (*(args[myidx])) {
3373 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3374 file, linenum, args[0], args[myidx]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003376 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003377 goto out;
3378 }
Emeric Brun97679e72010-09-23 17:56:44 +02003379 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003380 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003381 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003382 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003383
Emeric Brunb982a3d2010-01-04 15:45:53 +01003384 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3385 rule->cond = cond;
3386 rule->expr = expr;
3387 rule->flags = flags;
3388 rule->table.name = name ? strdup(name) : NULL;
3389 LIST_INIT(&rule->list);
3390 if (flags & STK_ON_RSP)
3391 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3392 else
3393 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 else if (!strcmp(args[0], "stats")) {
3396 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3397 curproxy->uri_auth = NULL; /* we must detach from the default config */
3398
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003399 if (!*args[1]) {
3400 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003401 } else if (!strcmp(args[1], "admin")) {
3402 struct stats_admin_rule *rule;
3403
3404 if (curproxy == &defproxy) {
3405 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409
3410 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3411 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3412 err_code |= ERR_ALERT | ERR_ABORT;
3413 goto out;
3414 }
3415
3416 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3417 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3418 file, linenum, args[0], args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003422 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3423 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3424 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
3427 }
3428
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003429 err_code |= warnif_cond_conflicts(cond,
3430 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3431 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003432
3433 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3434 rule->cond = cond;
3435 LIST_INIT(&rule->list);
3436 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 } else if (!strcmp(args[1], "uri")) {
3438 if (*(args[2]) == 0) {
3439 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\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_set_uri(&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], "realm")) {
3448 if (*(args[2]) == 0) {
3449 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_ABORT;
3455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003457 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003458 unsigned interval;
3459
3460 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3461 if (err) {
3462 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3463 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003466 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3467 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_ABORT;
3469 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003470 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003471 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003472 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003473
3474 if (curproxy == &defproxy) {
3475 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
3478 }
3479
3480 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3481 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3482 err_code |= ERR_ALERT | ERR_ABORT;
3483 goto out;
3484 }
3485
Willy Tarreauff011f22011-01-06 17:51:27 +01003486 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3487 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003488 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3489 file, linenum, args[0]);
3490 err_code |= ERR_WARN;
3491 }
3492
Willy Tarreauff011f22011-01-06 17:51:27 +01003493 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003494
Willy Tarreauff011f22011-01-06 17:51:27 +01003495 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003496 err_code |= ERR_ALERT | ERR_ABORT;
3497 goto out;
3498 }
3499
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003500 err_code |= warnif_cond_conflicts(rule->cond,
3501 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3502 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003503 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003504
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 } else if (!strcmp(args[1], "auth")) {
3506 if (*(args[2]) == 0) {
3507 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3511 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_ABORT;
3513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515 } else if (!strcmp(args[1], "scope")) {
3516 if (*(args[2]) == 0) {
3517 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3521 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_ABORT;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525 } else if (!strcmp(args[1], "enable")) {
3526 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3527 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_ABORT;
3529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003531 } else if (!strcmp(args[1], "hide-version")) {
3532 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3533 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_ABORT;
3535 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003536 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003537 } else if (!strcmp(args[1], "show-legends")) {
3538 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3539 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3540 err_code |= ERR_ALERT | ERR_ABORT;
3541 goto out;
3542 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003543 } else if (!strcmp(args[1], "show-node")) {
3544
3545 if (*args[2]) {
3546 int i;
3547 char c;
3548
3549 for (i=0; args[2][i]; i++) {
3550 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003551 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3552 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003553 break;
3554 }
3555
3556 if (!i || args[2][i]) {
3557 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3558 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3559 file, linenum, args[0], args[1]);
3560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
3562 }
3563 }
3564
3565 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3566 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3567 err_code |= ERR_ALERT | ERR_ABORT;
3568 goto out;
3569 }
3570 } else if (!strcmp(args[1], "show-desc")) {
3571 char *desc = NULL;
3572
3573 if (*args[2]) {
3574 int i, len=0;
3575 char *d;
3576
Willy Tarreau348acfe2014-04-14 15:00:39 +02003577 for (i = 2; *args[i]; i++)
3578 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003579
3580 desc = d = (char *)calloc(1, len);
3581
Willy Tarreau348acfe2014-04-14 15:00:39 +02003582 d += snprintf(d, desc + len - d, "%s", args[2]);
3583 for (i = 3; *args[i]; i++)
3584 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003585 }
3586
3587 if (!*args[2] && !global.desc)
3588 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3589 file, linenum, args[1]);
3590 else {
3591 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3592 free(desc);
3593 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3594 err_code |= ERR_ALERT | ERR_ABORT;
3595 goto out;
3596 }
3597 free(desc);
3598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003600stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003601 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 +01003602 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606 }
3607 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003608 int optnum;
3609
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003610 if (*(args[1]) == '\0') {
3611 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3612 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003616
3617 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3618 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003619 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3620 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3621 file, linenum, cfg_opts[optnum].name);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
Willy Tarreau93893792009-07-23 13:19:11 +02003625 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3626 err_code |= ERR_WARN;
3627 goto out;
3628 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003629
Willy Tarreau3842f002009-06-14 11:39:52 +02003630 curproxy->no_options &= ~cfg_opts[optnum].val;
3631 curproxy->options &= ~cfg_opts[optnum].val;
3632
3633 switch (kwm) {
3634 case KWM_STD:
3635 curproxy->options |= cfg_opts[optnum].val;
3636 break;
3637 case KWM_NO:
3638 curproxy->no_options |= cfg_opts[optnum].val;
3639 break;
3640 case KWM_DEF: /* already cleared */
3641 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003642 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003643
Willy Tarreau93893792009-07-23 13:19:11 +02003644 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003645 }
3646 }
3647
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003648 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3649 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003650 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3651 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3652 file, linenum, cfg_opts2[optnum].name);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
Willy Tarreau93893792009-07-23 13:19:11 +02003656 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3657 err_code |= ERR_WARN;
3658 goto out;
3659 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003660
Willy Tarreau3842f002009-06-14 11:39:52 +02003661 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3662 curproxy->options2 &= ~cfg_opts2[optnum].val;
3663
3664 switch (kwm) {
3665 case KWM_STD:
3666 curproxy->options2 |= cfg_opts2[optnum].val;
3667 break;
3668 case KWM_NO:
3669 curproxy->no_options2 |= cfg_opts2[optnum].val;
3670 break;
3671 case KWM_DEF: /* already cleared */
3672 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003673 }
Willy Tarreau93893792009-07-23 13:19:11 +02003674 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003675 }
3676 }
3677
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003678 /* HTTP options override each other. They can be cancelled using
3679 * "no option xxx" which only switches to default mode if the mode
3680 * was this one (useful for cancelling options set in defaults
3681 * sections).
3682 */
3683 if (strcmp(args[1], "httpclose") == 0) {
3684 if (kwm == KWM_STD) {
3685 curproxy->options &= ~PR_O_HTTP_MODE;
3686 curproxy->options |= PR_O_HTTP_PCL;
3687 goto out;
3688 }
3689 else if (kwm == KWM_NO) {
3690 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3691 curproxy->options &= ~PR_O_HTTP_MODE;
3692 goto out;
3693 }
3694 }
3695 else if (strcmp(args[1], "forceclose") == 0) {
3696 if (kwm == KWM_STD) {
3697 curproxy->options &= ~PR_O_HTTP_MODE;
3698 curproxy->options |= PR_O_HTTP_FCL;
3699 goto out;
3700 }
3701 else if (kwm == KWM_NO) {
3702 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3703 curproxy->options &= ~PR_O_HTTP_MODE;
3704 goto out;
3705 }
3706 }
3707 else if (strcmp(args[1], "http-server-close") == 0) {
3708 if (kwm == KWM_STD) {
3709 curproxy->options &= ~PR_O_HTTP_MODE;
3710 curproxy->options |= PR_O_HTTP_SCL;
3711 goto out;
3712 }
3713 else if (kwm == KWM_NO) {
3714 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3715 curproxy->options &= ~PR_O_HTTP_MODE;
3716 goto out;
3717 }
3718 }
3719 else if (strcmp(args[1], "http-keep-alive") == 0) {
3720 if (kwm == KWM_STD) {
3721 curproxy->options &= ~PR_O_HTTP_MODE;
3722 curproxy->options |= PR_O_HTTP_KAL;
3723 goto out;
3724 }
3725 else if (kwm == KWM_NO) {
3726 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3727 curproxy->options &= ~PR_O_HTTP_MODE;
3728 goto out;
3729 }
3730 }
3731 else if (strcmp(args[1], "http-tunnel") == 0) {
3732 if (kwm == KWM_STD) {
3733 curproxy->options &= ~PR_O_HTTP_MODE;
3734 curproxy->options |= PR_O_HTTP_TUN;
3735 goto out;
3736 }
3737 else if (kwm == KWM_NO) {
3738 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3739 curproxy->options &= ~PR_O_HTTP_MODE;
3740 goto out;
3741 }
3742 }
3743
Willy Tarreau3842f002009-06-14 11:39:52 +02003744 if (kwm != KWM_STD) {
3745 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003746 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003749 }
3750
Emeric Brun3a058f32009-06-30 18:26:00 +02003751 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003752 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003754 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003755 if (*(args[2]) != '\0') {
3756 if (!strcmp(args[2], "clf")) {
3757 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003758 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003759 } else {
3760 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003763 }
3764 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003765 if (curproxy->conf.logformat_string != default_http_log_format &&
3766 curproxy->conf.logformat_string != default_tcp_log_format &&
3767 curproxy->conf.logformat_string != clf_http_log_format)
3768 free(curproxy->conf.logformat_string);
3769 curproxy->conf.logformat_string = logformat;
3770
3771 free(curproxy->conf.lfs_file);
3772 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3773 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003774 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003775 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003777 if (curproxy->conf.logformat_string != default_http_log_format &&
3778 curproxy->conf.logformat_string != default_tcp_log_format &&
3779 curproxy->conf.logformat_string != clf_http_log_format)
3780 free(curproxy->conf.logformat_string);
3781 curproxy->conf.logformat_string = default_tcp_log_format;
3782
3783 free(curproxy->conf.lfs_file);
3784 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3785 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 else if (!strcmp(args[1], "tcpka")) {
3788 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003789 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003791
3792 if (curproxy->cap & PR_CAP_FE)
3793 curproxy->options |= PR_O_TCP_CLI_KA;
3794 if (curproxy->cap & PR_CAP_BE)
3795 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
3797 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
3800
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003802 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003803 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003804 curproxy->options2 &= ~PR_O2_CHK_ANY;
3805 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 if (!*args[2]) { /* no argument */
3807 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3808 curproxy->check_len = strlen(DEF_CHECK_REQ);
3809 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003810 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 curproxy->check_req = (char *)malloc(reqlen);
3812 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003813 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003815 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 if (*args[4])
3817 reqlen += strlen(args[4]);
3818 else
3819 reqlen += strlen("HTTP/1.0");
3820
3821 curproxy->check_req = (char *)malloc(reqlen);
3822 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003823 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003825 }
3826 else if (!strcmp(args[1], "ssl-hello-chk")) {
3827 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003830
Willy Tarreaua534fea2008-08-03 12:19:50 +02003831 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003832 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003833 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003834 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
Willy Tarreau23677902007-05-08 23:50:35 +02003836 else if (!strcmp(args[1], "smtpchk")) {
3837 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003838 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003839 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options2 &= ~PR_O2_CHK_ANY;
3841 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003842
3843 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3844 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3845 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3846 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3847 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3848 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3849 curproxy->check_req = (char *)malloc(reqlen);
3850 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3851 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3852 } else {
3853 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3854 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3855 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3856 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3857 }
3858 }
3859 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003860 else if (!strcmp(args[1], "pgsql-check")) {
3861 /* use PostgreSQL request to check servers' health */
3862 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3863 err_code |= ERR_WARN;
3864
3865 free(curproxy->check_req);
3866 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003867 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003868 curproxy->options2 |= PR_O2_PGSQL_CHK;
3869
3870 if (*(args[2])) {
3871 int cur_arg = 2;
3872
3873 while (*(args[cur_arg])) {
3874 if (strcmp(args[cur_arg], "user") == 0) {
3875 char * packet;
3876 uint32_t packet_len;
3877 uint32_t pv;
3878
3879 /* suboption header - needs additional argument for it */
3880 if (*(args[cur_arg+1]) == 0) {
3881 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3882 file, linenum, args[0], args[1], args[cur_arg]);
3883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
3885 }
3886
3887 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3888 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3889 pv = htonl(0x30000); /* protocol version 3.0 */
3890
3891 packet = (char*) calloc(1, packet_len);
3892
3893 memcpy(packet + 4, &pv, 4);
3894
3895 /* copy "user" */
3896 memcpy(packet + 8, "user", 4);
3897
3898 /* copy username */
3899 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3900
3901 free(curproxy->check_req);
3902 curproxy->check_req = packet;
3903 curproxy->check_len = packet_len;
3904
3905 packet_len = htonl(packet_len);
3906 memcpy(packet, &packet_len, 4);
3907 cur_arg += 2;
3908 } else {
3909 /* unknown suboption - catchall */
3910 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3911 file, linenum, args[0], args[1]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915 } /* end while loop */
3916 }
3917 }
3918
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003919 else if (!strcmp(args[1], "redis-check")) {
3920 /* use REDIS PING request to check servers' health */
3921 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3922 err_code |= ERR_WARN;
3923
3924 free(curproxy->check_req);
3925 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003926 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003927 curproxy->options2 |= PR_O2_REDIS_CHK;
3928
3929 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3930 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3931 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3932 }
3933
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003934 else if (!strcmp(args[1], "mysql-check")) {
3935 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003936 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3937 err_code |= ERR_WARN;
3938
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003939 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003940 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003941 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003942 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003943
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003944 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003945 * const char mysql40_client_auth_pkt[] = {
3946 * "\x0e\x00\x00" // packet length
3947 * "\x01" // packet number
3948 * "\x00\x00" // client capabilities
3949 * "\x00\x00\x01" // max packet
3950 * "haproxy\x00" // username (null terminated string)
3951 * "\x00" // filler (always 0x00)
3952 * "\x01\x00\x00" // packet length
3953 * "\x00" // packet number
3954 * "\x01" // COM_QUIT command
3955 * };
3956 */
3957
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003958 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3959 * const char mysql41_client_auth_pkt[] = {
3960 * "\x0e\x00\x00\" // packet length
3961 * "\x01" // packet number
3962 * "\x00\x00\x00\x00" // client capabilities
3963 * "\x00\x00\x00\x01" // max packet
3964 * "\x21" // character set (UTF-8)
3965 * char[23] // All zeroes
3966 * "haproxy\x00" // username (null terminated string)
3967 * "\x00" // filler (always 0x00)
3968 * "\x01\x00\x00" // packet length
3969 * "\x00" // packet number
3970 * "\x01" // COM_QUIT command
3971 * };
3972 */
3973
3974
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003975 if (*(args[2])) {
3976 int cur_arg = 2;
3977
3978 while (*(args[cur_arg])) {
3979 if (strcmp(args[cur_arg], "user") == 0) {
3980 char *mysqluser;
3981 int packetlen, reqlen, userlen;
3982
3983 /* suboption header - needs additional argument for it */
3984 if (*(args[cur_arg+1]) == 0) {
3985 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3986 file, linenum, args[0], args[1], args[cur_arg]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990 mysqluser = args[cur_arg + 1];
3991 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003992
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003993 if (*(args[cur_arg+2])) {
3994 if (!strcmp(args[cur_arg+2], "post-41")) {
3995 packetlen = userlen + 7 + 27;
3996 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003997
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003998 free(curproxy->check_req);
3999 curproxy->check_req = (char *)calloc(1, reqlen);
4000 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004001
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004002 snprintf(curproxy->check_req, 4, "%c%c%c",
4003 ((unsigned char) packetlen & 0xff),
4004 ((unsigned char) (packetlen >> 8) & 0xff),
4005 ((unsigned char) (packetlen >> 16) & 0xff));
4006
4007 curproxy->check_req[3] = 1;
4008 curproxy->check_req[5] = 130;
4009 curproxy->check_req[11] = 1;
4010 curproxy->check_req[12] = 33;
4011 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4012 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4013 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4014 cur_arg += 3;
4015 } else {
4016 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020 } else {
4021 packetlen = userlen + 7;
4022 reqlen = packetlen + 9;
4023
4024 free(curproxy->check_req);
4025 curproxy->check_req = (char *)calloc(1, reqlen);
4026 curproxy->check_len = reqlen;
4027
4028 snprintf(curproxy->check_req, 4, "%c%c%c",
4029 ((unsigned char) packetlen & 0xff),
4030 ((unsigned char) (packetlen >> 8) & 0xff),
4031 ((unsigned char) (packetlen >> 16) & 0xff));
4032
4033 curproxy->check_req[3] = 1;
4034 curproxy->check_req[5] = 128;
4035 curproxy->check_req[8] = 1;
4036 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4037 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4038 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4039 cur_arg += 2;
4040 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004041 } else {
4042 /* unknown suboption - catchall */
4043 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4044 file, linenum, args[0], args[1]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
4048 } /* end while loop */
4049 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004050 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004051 else if (!strcmp(args[1], "ldap-check")) {
4052 /* use LDAP request to check servers' health */
4053 free(curproxy->check_req);
4054 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004055 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004056 curproxy->options2 |= PR_O2_LDAP_CHK;
4057
4058 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4059 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4060 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4061 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004062 else if (!strcmp(args[1], "tcp-check")) {
4063 /* use raw TCPCHK send/expect to check servers' health */
4064 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4065 err_code |= ERR_WARN;
4066
4067 free(curproxy->check_req);
4068 curproxy->check_req = NULL;
4069 curproxy->options2 &= ~PR_O2_CHK_ANY;
4070 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4071 }
Simon Horman98637e52014-06-20 12:30:16 +09004072 else if (!strcmp(args[1], "external-check")) {
4073 /* excute an external command to check servers' health */
4074 free(curproxy->check_req);
4075 curproxy->check_req = NULL;
4076 curproxy->options2 &= ~PR_O2_CHK_ANY;
4077 curproxy->options2 |= PR_O2_EXT_CHK;
4078 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004079 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004080 int cur_arg;
4081
4082 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4083 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004084 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004085
Willy Tarreau87cf5142011-08-19 22:57:24 +02004086 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004087
4088 free(curproxy->fwdfor_hdr_name);
4089 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4090 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4091
4092 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4093 cur_arg = 2;
4094 while (*(args[cur_arg])) {
4095 if (!strcmp(args[cur_arg], "except")) {
4096 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004097 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004098 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4099 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004102 }
4103 /* flush useless bits */
4104 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004105 cur_arg += 2;
4106 } else if (!strcmp(args[cur_arg], "header")) {
4107 /* suboption header - needs additional argument for it */
4108 if (*(args[cur_arg+1]) == 0) {
4109 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4110 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004113 }
4114 free(curproxy->fwdfor_hdr_name);
4115 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4116 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4117 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004118 } else if (!strcmp(args[cur_arg], "if-none")) {
4119 curproxy->options &= ~PR_O_FF_ALWAYS;
4120 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004121 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004122 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004123 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004124 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004127 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004128 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004129 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004130 else if (!strcmp(args[1], "originalto")) {
4131 int cur_arg;
4132
4133 /* insert x-original-to field, but not for the IP address listed as an except.
4134 * set default options (ie: bitfield, header name, etc)
4135 */
4136
4137 curproxy->options |= PR_O_ORGTO;
4138
4139 free(curproxy->orgto_hdr_name);
4140 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4141 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4142
Willy Tarreau87cf5142011-08-19 22:57:24 +02004143 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004144 cur_arg = 2;
4145 while (*(args[cur_arg])) {
4146 if (!strcmp(args[cur_arg], "except")) {
4147 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004148 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 +02004149 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4150 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004153 }
4154 /* flush useless bits */
4155 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4156 cur_arg += 2;
4157 } else if (!strcmp(args[cur_arg], "header")) {
4158 /* suboption header - needs additional argument for it */
4159 if (*(args[cur_arg+1]) == 0) {
4160 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4161 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004164 }
4165 free(curproxy->orgto_hdr_name);
4166 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4167 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4168 cur_arg += 2;
4169 } else {
4170 /* unknown suboption - catchall */
4171 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4172 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004175 }
4176 } /* end while loop */
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else {
4179 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 }
Willy Tarreau93893792009-07-23 13:19:11 +02004183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004185 else if (!strcmp(args[0], "default_backend")) {
4186 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004188
4189 if (*(args[1]) == 0) {
4190 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004193 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004194 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004195 curproxy->defbe.name = strdup(args[1]);
4196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004198 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004200
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004201 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4202 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 +01004203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 /* enable reconnections to dispatch */
4206 curproxy->options |= PR_O_REDISP;
4207 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004208 else if (!strcmp(args[0], "http-check")) {
4209 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004211
4212 if (strcmp(args[1], "disable-on-404") == 0) {
4213 /* enable a graceful server shutdown on an HTTP 404 response */
4214 curproxy->options |= PR_O_DISABLE404;
4215 }
Willy Tarreauef781042010-01-27 11:53:01 +01004216 else if (strcmp(args[1], "send-state") == 0) {
4217 /* enable emission of the apparent state of a server in HTTP checks */
4218 curproxy->options2 |= PR_O2_CHK_SNDST;
4219 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004220 else if (strcmp(args[1], "expect") == 0) {
4221 const char *ptr_arg;
4222 int cur_arg;
4223
4224 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4225 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
4229
4230 cur_arg = 2;
4231 /* consider exclamation marks, sole or at the beginning of a word */
4232 while (*(ptr_arg = args[cur_arg])) {
4233 while (*ptr_arg == '!') {
4234 curproxy->options2 ^= PR_O2_EXP_INV;
4235 ptr_arg++;
4236 }
4237 if (*ptr_arg)
4238 break;
4239 cur_arg++;
4240 }
4241 /* now ptr_arg points to the beginning of a word past any possible
4242 * exclamation mark, and cur_arg is the argument which holds this word.
4243 */
4244 if (strcmp(ptr_arg, "status") == 0) {
4245 if (!*(args[cur_arg + 1])) {
4246 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4247 file, linenum, args[0], args[1], ptr_arg);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004252 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004253 curproxy->expect_str = strdup(args[cur_arg + 1]);
4254 }
4255 else if (strcmp(ptr_arg, "string") == 0) {
4256 if (!*(args[cur_arg + 1])) {
4257 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4258 file, linenum, args[0], args[1], ptr_arg);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004263 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004264 curproxy->expect_str = strdup(args[cur_arg + 1]);
4265 }
4266 else if (strcmp(ptr_arg, "rstatus") == 0) {
4267 if (!*(args[cur_arg + 1])) {
4268 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4269 file, linenum, args[0], args[1], ptr_arg);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004274 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004275 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004276 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004277 free(curproxy->expect_regex);
4278 curproxy->expect_regex = NULL;
4279 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004280 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004281 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4282 error = NULL;
4283 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4284 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4285 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4286 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
4289 }
4290 }
4291 else if (strcmp(ptr_arg, "rstring") == 0) {
4292 if (!*(args[cur_arg + 1])) {
4293 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4294 file, linenum, args[0], args[1], ptr_arg);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004299 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004300 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004301 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004302 free(curproxy->expect_regex);
4303 curproxy->expect_regex = NULL;
4304 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004305 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004306 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4307 error = NULL;
4308 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4309 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4310 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4311 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315 }
4316 else {
4317 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4318 file, linenum, args[0], args[1], ptr_arg);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004323 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004324 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 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004327 }
4328 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004329 else if (!strcmp(args[0], "tcp-check")) {
4330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4331 err_code |= ERR_WARN;
4332
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004333 if (strcmp(args[1], "connect") == 0) {
4334 const char *ptr_arg;
4335 int cur_arg;
4336 struct tcpcheck_rule *tcpcheck;
4337 struct list *l;
4338
4339 /* check if first rule is also a 'connect' action */
4340 l = (struct list *)&curproxy->tcpcheck_rules;
4341 if (l->p != l->n) {
4342 tcpcheck = (struct tcpcheck_rule *)l->n;
4343 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4344 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4345 file, linenum);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349 }
4350
4351 cur_arg = 2;
4352 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4353 tcpcheck->action = TCPCHK_ACT_CONNECT;
4354
4355 /* parsing each parameters to fill up the rule */
4356 while (*(ptr_arg = args[cur_arg])) {
4357 /* tcp port */
4358 if (strcmp(args[cur_arg], "port") == 0) {
4359 if ( (atol(args[cur_arg + 1]) > 65535) ||
4360 (atol(args[cur_arg + 1]) < 1) ){
4361 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4362 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
4365 }
4366 tcpcheck->port = atol(args[cur_arg + 1]);
4367 cur_arg += 2;
4368 }
4369 /* send proxy protocol */
4370 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4371 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4372 cur_arg++;
4373 }
4374#ifdef USE_OPENSSL
4375 else if (strcmp(args[cur_arg], "ssl") == 0) {
4376 curproxy->options |= PR_O_TCPCHK_SSL;
4377 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4378 cur_arg++;
4379 }
4380#endif /* USE_OPENSSL */
4381 else {
4382#ifdef USE_OPENSSL
4383 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4384#else /* USE_OPENSSL */
4385 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4386#endif /* USE_OPENSSL */
4387 file, linenum, args[0], args[1], args[cur_arg]);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391
4392 }
4393
4394 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4395 }
4396 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004397 if (! *(args[2]) ) {
4398 /* SEND string expected */
4399 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4400 file, linenum, args[0], args[1], args[2]);
4401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
4403 } else {
4404 struct tcpcheck_rule *tcpcheck;
4405
4406 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4407
4408 tcpcheck->action = TCPCHK_ACT_SEND;
4409 tcpcheck->string_len = strlen(args[2]);
4410 tcpcheck->string = strdup(args[2]);
4411 tcpcheck->expect_regex = NULL;
4412
4413 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4414 }
4415 }
4416 else if (strcmp(args[1], "send-binary") == 0) {
4417 if (! *(args[2]) ) {
4418 /* SEND binary string expected */
4419 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4420 file, linenum, args[0], args[1], args[2]);
4421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
4423 } else {
4424 struct tcpcheck_rule *tcpcheck;
4425 char *err = NULL;
4426
4427 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4428
4429 tcpcheck->action = TCPCHK_ACT_SEND;
4430 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4431 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4432 file, linenum, args[0], args[1], args[2], err);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 }
4436 tcpcheck->expect_regex = NULL;
4437
4438 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4439 }
4440 }
4441 else if (strcmp(args[1], "expect") == 0) {
4442 const char *ptr_arg;
4443 int cur_arg;
4444 int inverse = 0;
4445
4446 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4447 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
4451
4452 cur_arg = 2;
4453 /* consider exclamation marks, sole or at the beginning of a word */
4454 while (*(ptr_arg = args[cur_arg])) {
4455 while (*ptr_arg == '!') {
4456 inverse = !inverse;
4457 ptr_arg++;
4458 }
4459 if (*ptr_arg)
4460 break;
4461 cur_arg++;
4462 }
4463 /* now ptr_arg points to the beginning of a word past any possible
4464 * exclamation mark, and cur_arg is the argument which holds this word.
4465 */
4466 if (strcmp(ptr_arg, "binary") == 0) {
4467 if (!*(args[cur_arg + 1])) {
4468 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4469 file, linenum, args[0], args[1], ptr_arg);
4470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
4472 }
4473 struct tcpcheck_rule *tcpcheck;
4474 char *err = NULL;
4475
4476 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4477
4478 tcpcheck->action = TCPCHK_ACT_EXPECT;
4479 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4480 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4481 file, linenum, args[0], args[1], args[2], err);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
4485 tcpcheck->expect_regex = NULL;
4486 tcpcheck->inverse = inverse;
4487
4488 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4489 }
4490 else if (strcmp(ptr_arg, "string") == 0) {
4491 if (!*(args[cur_arg + 1])) {
4492 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4493 file, linenum, args[0], args[1], ptr_arg);
4494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
4496 }
4497 struct tcpcheck_rule *tcpcheck;
4498
4499 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4500
4501 tcpcheck->action = TCPCHK_ACT_EXPECT;
4502 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4503 tcpcheck->string = strdup(args[cur_arg + 1]);
4504 tcpcheck->expect_regex = NULL;
4505 tcpcheck->inverse = inverse;
4506
4507 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4508 }
4509 else if (strcmp(ptr_arg, "rstring") == 0) {
4510 if (!*(args[cur_arg + 1])) {
4511 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4512 file, linenum, args[0], args[1], ptr_arg);
4513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
4515 }
4516 struct tcpcheck_rule *tcpcheck;
4517
4518 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4519
4520 tcpcheck->action = TCPCHK_ACT_EXPECT;
4521 tcpcheck->string_len = 0;
4522 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004523 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4524 error = NULL;
4525 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4526 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4527 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4528 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
4532 tcpcheck->inverse = inverse;
4533
4534 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4535 }
4536 else {
4537 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4538 file, linenum, args[0], args[1], ptr_arg);
4539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
4541 }
4542 }
4543 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004544 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
4547 }
4548 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004549 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004550 if (curproxy == &defproxy) {
4551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004554 }
4555
Willy Tarreaub80c2302007-11-30 20:51:32 +01004556 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004558
4559 if (strcmp(args[1], "fail") == 0) {
4560 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004561 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004562 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4563 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004566 }
4567
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004568 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4569 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4570 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004573 }
4574 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4575 }
4576 else {
4577 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004580 }
4581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582#ifdef TPROXY
4583 else if (!strcmp(args[0], "transparent")) {
4584 /* enable transparent proxy connections */
4585 curproxy->options |= PR_O_TRANSP;
4586 }
4587#endif
4588 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004591
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 if (*(args[1]) == 0) {
4593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
4597 curproxy->maxconn = atol(args[1]);
4598 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004599 else if (!strcmp(args[0], "backlog")) { /* backlog */
4600 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004601 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004602
4603 if (*(args[1]) == 0) {
4604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004607 }
4608 curproxy->backlog = atol(args[1]);
4609 }
Willy Tarreau86034312006-12-29 00:10:33 +01004610 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004613
Willy Tarreau86034312006-12-29 00:10:33 +01004614 if (*(args[1]) == 0) {
4615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004618 }
4619 curproxy->fullconn = atol(args[1]);
4620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4622 if (*(args[1]) == 0) {
4623 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004627 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4628 if (err) {
4629 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4630 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004633 }
4634 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
4636 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004637 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004638 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004639 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004640
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 if (curproxy == &defproxy) {
4642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004646 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004648
Willy Tarreau902636f2013-03-10 19:44:48 +01004649 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004650 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004651 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004652 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004653 goto out;
4654 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004655
4656 proto = protocol_by_family(sk->ss_family);
4657 if (!proto || !proto->connect) {
4658 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4659 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004660 err_code |= ERR_ALERT | ERR_FATAL;
4661 goto out;
4662 }
4663
4664 if (port1 != port2) {
4665 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004670
4671 if (!port1) {
4672 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4673 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004677
Willy Tarreaud5191e72010-02-09 20:50:45 +01004678 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004679 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 }
4681 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004682 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004683 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004684
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004685 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4686 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004687 err_code |= ERR_ALERT | ERR_FATAL;
4688 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004691 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004692 /**
4693 * The syntax for hash-type config element is
4694 * hash-type {map-based|consistent} [[<algo>] avalanche]
4695 *
4696 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4697 */
4698 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004699
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004700 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4701 err_code |= ERR_WARN;
4702
4703 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004704 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4705 }
4706 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004707 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4708 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004709 else if (strcmp(args[1], "avalanche") == 0) {
4710 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]);
4711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004713 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004714 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004715 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718 }
Bhaskar98634f02013-10-29 23:30:51 -04004719
4720 /* set the hash function to use */
4721 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004722 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004723 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004724
4725 /* if consistent with no argument, then avalanche modifier is also applied */
4726 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4727 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004728 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004729 /* set the hash function */
4730 if (!strcmp(args[2], "sdbm")) {
4731 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4732 }
4733 else if (!strcmp(args[2], "djb2")) {
4734 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004735 } else if (!strcmp(args[2], "wt6")) {
4736 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004737 }
4738 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004739 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 -05004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
4743
4744 /* set the hash modifier */
4745 if (!strcmp(args[3], "avalanche")) {
4746 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4747 }
4748 else if (*args[3]) {
4749 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
4752 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004753 }
William Lallemanda73203e2012-03-12 12:48:57 +01004754 }
William Lallemanda73203e2012-03-12 12:48:57 +01004755 else if (strcmp(args[0], "unique-id-format") == 0) {
4756 if (!*(args[1])) {
4757 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
4760 }
William Lallemand3203ff42012-11-11 17:30:56 +01004761 if (*(args[2])) {
4762 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004766 free(curproxy->conf.uniqueid_format_string);
4767 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004768
Willy Tarreau62a61232013-04-12 18:13:46 +02004769 free(curproxy->conf.uif_file);
4770 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4771 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004772 }
William Lallemanda73203e2012-03-12 12:48:57 +01004773
4774 else if (strcmp(args[0], "unique-id-header") == 0) {
4775 if (!*(args[1])) {
4776 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
4780 free(curproxy->header_unique_id);
4781 curproxy->header_unique_id = strdup(args[1]);
4782 }
4783
William Lallemand723b73a2012-02-08 16:37:49 +01004784 else if (strcmp(args[0], "log-format") == 0) {
4785 if (!*(args[1])) {
4786 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
William Lallemand3203ff42012-11-11 17:30:56 +01004790 if (*(args[2])) {
4791 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004795
Willy Tarreau62a61232013-04-12 18:13:46 +02004796 if (curproxy->conf.logformat_string != default_http_log_format &&
4797 curproxy->conf.logformat_string != default_tcp_log_format &&
4798 curproxy->conf.logformat_string != clf_http_log_format)
4799 free(curproxy->conf.logformat_string);
4800 curproxy->conf.logformat_string = strdup(args[1]);
4801
4802 free(curproxy->conf.lfs_file);
4803 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4804 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004805
4806 /* get a chance to improve log-format error reporting by
4807 * reporting the correct line-number when possible.
4808 */
4809 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4810 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4811 file, linenum, curproxy->id);
4812 err_code |= ERR_WARN;
4813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
William Lallemand723b73a2012-02-08 16:37:49 +01004815
William Lallemand0f99e342011-10-12 17:50:54 +02004816 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4817 /* delete previous herited or defined syslog servers */
4818 struct logsrv *back;
4819
4820 if (*(args[1]) != 0) {
4821 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
4825
William Lallemand723b73a2012-02-08 16:37:49 +01004826 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4827 LIST_DEL(&tmplogsrv->list);
4828 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004829 }
4830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004832 struct logsrv *logsrv;
4833
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004835 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004836 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004837 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004838 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004839 LIST_INIT(&node->list);
4840 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004844 struct sockaddr_storage *sk;
4845 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004846
4847 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848
William Lallemand0f99e342011-10-12 17:50:54 +02004849 logsrv->facility = get_log_facility(args[2]);
4850 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
4856
William Lallemand0f99e342011-10-12 17:50:54 +02004857 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004859 logsrv->level = get_log_level(args[3]);
4860 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 }
4866 }
4867
William Lallemand0f99e342011-10-12 17:50:54 +02004868 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004869 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004870 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004871 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004872 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004876 }
4877 }
4878
Willy Tarreau902636f2013-03-10 19:44:48 +01004879 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004880 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004881 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004882 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004883 goto out;
4884 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004885
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004886 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004887
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004888 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004889 if (port1 != port2) {
4890 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4891 file, linenum, args[0], args[1]);
4892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
4895
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004896 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004897 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
William Lallemand0f99e342011-10-12 17:50:54 +02004899
4900 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
4902 else {
4903 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4904 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 }
4909 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004910 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004911 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004912 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004913 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004914
Willy Tarreau977b8e42006-12-29 14:19:17 +01004915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004917
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004919 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4920 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004924
4925 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004926 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4927 free(curproxy->conn_src.iface_name);
4928 curproxy->conn_src.iface_name = NULL;
4929 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004930
Willy Tarreau902636f2013-03-10 19:44:48 +01004931 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004932 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004933 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004934 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004935 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004936 goto out;
4937 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004938
4939 proto = protocol_by_family(sk->ss_family);
4940 if (!proto || !proto->connect) {
4941 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004942 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004946
4947 if (port1 != port2) {
4948 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4949 file, linenum, args[0], args[1]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953
Willy Tarreauef9a3602012-12-08 22:29:20 +01004954 curproxy->conn_src.source_addr = *sk;
4955 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004956
4957 cur_arg = 2;
4958 while (*(args[cur_arg])) {
4959 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004960#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4961#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02004962 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004963 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4964 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004967 }
4968#endif
4969 if (!*args[cur_arg + 1]) {
4970 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4971 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004974 }
4975
4976 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004977 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4978 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004979 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004980 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4981 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004982 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4983 char *name, *end;
4984
4985 name = args[cur_arg+1] + 7;
4986 while (isspace(*name))
4987 name++;
4988
4989 end = name;
4990 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4991 end++;
4992
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4994 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4995 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4996 curproxy->conn_src.bind_hdr_len = end - name;
4997 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4998 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4999 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005000
5001 /* now look for an occurrence number */
5002 while (isspace(*end))
5003 end++;
5004 if (*end == ',') {
5005 end++;
5006 name = end;
5007 if (*end == '-')
5008 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005009 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005010 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005011 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005012 }
5013
Willy Tarreauef9a3602012-12-08 22:29:20 +01005014 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005015 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5016 " occurrences values smaller than %d.\n",
5017 file, linenum, MAX_HDR_HISTORY);
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005021 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005022 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005023
Willy Tarreau902636f2013-03-10 19:44:48 +01005024 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005025 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005026 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005027 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005028 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005029 goto out;
5030 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005031
5032 proto = protocol_by_family(sk->ss_family);
5033 if (!proto || !proto->connect) {
5034 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5035 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005039
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005040 if (port1 != port2) {
5041 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5042 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005046 curproxy->conn_src.tproxy_addr = *sk;
5047 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005048 }
5049 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005050#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005051 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005052#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005053#else /* no TPROXY support */
5054 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005055 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005058#endif
5059 cur_arg += 2;
5060 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005061 }
5062
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005063 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5064#ifdef SO_BINDTODEVICE
5065 if (!*args[cur_arg + 1]) {
5066 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005070 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005071 free(curproxy->conn_src.iface_name);
5072 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5073 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005074 global.last_checks |= LSTCHK_NETADM;
5075#else
5076 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5077 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005080#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005081 cur_arg += 2;
5082 continue;
5083 }
5084 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005085 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005090 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5091 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5092 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5099 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103
5104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005105 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005106 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005112 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005113 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
5117 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005119 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005120 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
5124 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005125 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005126 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005127 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
5131 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005132 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005133 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005134 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005138 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005140 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005141 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005143 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005144 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005145 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005147 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005148 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005150 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005151
5152 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5153 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 +01005154 }
5155 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005158 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005161
5162 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5163 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 +01005164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172
5173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005175 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
5179 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005181 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005182 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005188 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005189 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
5193 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005195 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005196 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
5200 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005207 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005215 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005216
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 if (curproxy == &defproxy) {
5218 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005222 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 if (*(args[1]) == 0) {
5226 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005230
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005231 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005232 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5233 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5234 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005238 err_code |= warnif_cond_conflicts(cond,
5239 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5240 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005241 }
5242 else if (*args[2]) {
5243 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5244 file, linenum, args[0], args[2]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005249 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005250 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005251 wl->s = strdup(args[1]);
5252 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005253 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
5255 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005262
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005265 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
5269 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005272 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
5276 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005279 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005293 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005299 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005300 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
5304 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005306 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005307 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 }
5311 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005312 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 if (curproxy == &defproxy) {
5315 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005319 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 if (*(args[1]) == 0) {
5323 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_ALERT | ERR_FATAL;
5325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005328 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005329 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5330 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5331 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
5334 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005335 err_code |= warnif_cond_conflicts(cond,
5336 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5337 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005338 }
5339 else if (*args[2]) {
5340 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5341 file, linenum, args[0], args[2]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005346 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005347 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348 wl->s = strdup(args[1]);
5349 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "errorloc") ||
5352 !strcmp(args[0], "errorloc302") ||
5353 !strcmp(args[0], "errorloc303")) { /* error location */
5354 int errnum, errlen;
5355 char *err;
5356
Willy Tarreau977b8e42006-12-29 14:19:17 +01005357 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005359
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005361 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365
5366 errnum = atol(args[1]);
5367 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005368 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5369 err = malloc(errlen);
5370 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005372 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5373 err = malloc(errlen);
5374 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 }
5376
Willy Tarreau0f772532006-12-23 20:51:41 +01005377 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5378 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005379 chunk_destroy(&curproxy->errmsg[rc]);
5380 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005381 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005384
5385 if (rc >= HTTP_ERR_SIZE) {
5386 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5387 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 free(err);
5389 }
5390 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005391 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5392 int errnum, errlen, fd;
5393 char *err;
5394 struct stat stat;
5395
5396 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005398
5399 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005400 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005403 }
5404
5405 fd = open(args[2], O_RDONLY);
5406 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5407 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5408 file, linenum, args[2], args[1]);
5409 if (fd >= 0)
5410 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005413 }
5414
Willy Tarreau27a674e2009-08-17 07:23:33 +02005415 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005416 errlen = stat.st_size;
5417 } else {
5418 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005419 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005421 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005422 }
5423
5424 err = malloc(errlen); /* malloc() must succeed during parsing */
5425 errnum = read(fd, err, errlen);
5426 if (errnum != errlen) {
5427 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5428 file, linenum, args[2], args[1]);
5429 close(fd);
5430 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005433 }
5434 close(fd);
5435
5436 errnum = atol(args[1]);
5437 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5438 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005439 chunk_destroy(&curproxy->errmsg[rc]);
5440 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005441 break;
5442 }
5443 }
5444
5445 if (rc >= HTTP_ERR_SIZE) {
5446 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5447 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005449 free(err);
5450 }
5451 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005452 else if (!strcmp(args[0], "compression")) {
5453 struct comp *comp;
5454 if (curproxy->comp == NULL) {
5455 comp = calloc(1, sizeof(struct comp));
5456 curproxy->comp = comp;
5457 } else {
5458 comp = curproxy->comp;
5459 }
5460
5461 if (!strcmp(args[1], "algo")) {
5462 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005463 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005464
William Lallemand82fe75c2012-10-23 10:25:10 +02005465 cur_arg = 2;
5466 if (!*args[cur_arg]) {
5467 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5468 file, linenum, args[0]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472 while (*(args[cur_arg])) {
5473 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5474 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5475 file, linenum, args[0], args[cur_arg]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
William Lallemand552df672012-11-07 13:21:47 +01005479 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5480 curproxy->comp->algos->end(&ctx);
5481 } else {
5482 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5483 file, linenum, args[0], args[cur_arg]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005487 cur_arg ++;
5488 continue;
5489 }
5490 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005491 else if (!strcmp(args[1], "offload")) {
5492 comp->offload = 1;
5493 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005494 else if (!strcmp(args[1], "type")) {
5495 int cur_arg;
5496 cur_arg = 2;
5497 if (!*args[cur_arg]) {
5498 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5499 file, linenum, args[0]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 while (*(args[cur_arg])) {
5504 comp_append_type(comp, args[cur_arg]);
5505 cur_arg ++;
5506 continue;
5507 }
5508 }
5509 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005510 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005511 file, linenum, args[0]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005517 struct cfg_kw_list *kwl;
5518 int index;
5519
5520 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5521 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5522 if (kwl->kw[index].section != CFG_LISTEN)
5523 continue;
5524 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5525 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005526 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005527 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005528 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005531 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005532 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005533 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005534 err_code |= ERR_WARN;
5535 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005536 }
Willy Tarreau93893792009-07-23 13:19:11 +02005537 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005538 }
5539 }
5540 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005541
Willy Tarreau6daf3432008-01-22 16:44:08 +01005542 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
Willy Tarreau93893792009-07-23 13:19:11 +02005546 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005547 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549}
5550
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005551int
5552cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5553{
5554
5555 int err_code = 0;
5556 const char *err;
5557
5558 if (!strcmp(args[0], "userlist")) { /* new userlist */
5559 struct userlist *newul;
5560
5561 if (!*args[1]) {
5562 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5563 file, linenum, args[0]);
5564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567
5568 err = invalid_char(args[1]);
5569 if (err) {
5570 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5571 file, linenum, *err, args[0], args[1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575
5576 for (newul = userlist; newul; newul = newul->next)
5577 if (!strcmp(newul->name, args[1])) {
5578 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5579 file, linenum, args[1]);
5580 err_code |= ERR_WARN;
5581 goto out;
5582 }
5583
5584 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5585 if (!newul) {
5586 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5587 err_code |= ERR_ALERT | ERR_ABORT;
5588 goto out;
5589 }
5590
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005591 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005592 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005593 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5594 err_code |= ERR_ALERT | ERR_ABORT;
5595 goto out;
5596 }
5597
5598 newul->next = userlist;
5599 userlist = newul;
5600
5601 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005602 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005603 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005604 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005605
5606 if (!*args[1]) {
5607 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5608 file, linenum, args[0]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612
5613 err = invalid_char(args[1]);
5614 if (err) {
5615 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5616 file, linenum, *err, args[0], args[1]);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 }
5620
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005621 for (ag = userlist->groups; ag; ag = ag->next)
5622 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005623 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5624 file, linenum, args[1], userlist->name);
5625 err_code |= ERR_ALERT;
5626 goto out;
5627 }
5628
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005629 ag = calloc(1, sizeof(*ag));
5630 if (!ag) {
5631 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5632 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005633 goto out;
5634 }
5635
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005636 ag->name = strdup(args[1]);
5637 if (!ag) {
5638 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5639 err_code |= ERR_ALERT | ERR_ABORT;
5640 goto out;
5641 }
5642
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005643 cur_arg = 2;
5644
5645 while (*args[cur_arg]) {
5646 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005647 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005648 cur_arg += 2;
5649 continue;
5650 } else {
5651 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5652 file, linenum, args[0]);
5653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
5655 }
5656 }
5657
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005658 ag->next = userlist->groups;
5659 userlist->groups = ag;
5660
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005661 } else if (!strcmp(args[0], "user")) { /* new user */
5662 struct auth_users *newuser;
5663 int cur_arg;
5664
5665 if (!*args[1]) {
5666 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5667 file, linenum, args[0]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671
5672 for (newuser = userlist->users; newuser; newuser = newuser->next)
5673 if (!strcmp(newuser->user, args[1])) {
5674 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5675 file, linenum, args[1], userlist->name);
5676 err_code |= ERR_ALERT;
5677 goto out;
5678 }
5679
5680 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5681 if (!newuser) {
5682 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5683 err_code |= ERR_ALERT | ERR_ABORT;
5684 goto out;
5685 }
5686
5687 newuser->user = strdup(args[1]);
5688
5689 newuser->next = userlist->users;
5690 userlist->users = newuser;
5691
5692 cur_arg = 2;
5693
5694 while (*args[cur_arg]) {
5695 if (!strcmp(args[cur_arg], "password")) {
5696#ifndef CONFIG_HAP_CRYPT
5697 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5698 file, linenum);
5699 err_code |= ERR_ALERT;
5700#endif
5701 newuser->pass = strdup(args[cur_arg + 1]);
5702 cur_arg += 2;
5703 continue;
5704 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5705 newuser->pass = strdup(args[cur_arg + 1]);
5706 newuser->flags |= AU_O_INSECURE;
5707 cur_arg += 2;
5708 continue;
5709 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005710 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005711 cur_arg += 2;
5712 continue;
5713 } else {
5714 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5715 file, linenum, args[0]);
5716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
5719 }
5720 } else {
5721 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 }
5724
5725out:
5726 return err_code;
5727}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728
5729/*
5730 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005731 * Returns the error code, 0 if OK, or any combination of :
5732 * - ERR_ABORT: must abort ASAP
5733 * - ERR_FATAL: we can continue parsing but not start the service
5734 * - ERR_WARN: a warning has been emitted
5735 * - ERR_ALERT: an alert has been emitted
5736 * Only the two first ones can stop processing, the two others are just
5737 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005739int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005741 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 FILE *f;
5743 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005744 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005745 struct cfg_section *cs = NULL;
5746 struct cfg_section *ics;
5747
5748 /* Register internal sections */
5749 if (!cfg_register_section("listen", cfg_parse_listen) ||
5750 !cfg_register_section("frontend", cfg_parse_listen) ||
5751 !cfg_register_section("backend", cfg_parse_listen) ||
5752 !cfg_register_section("ruleset", cfg_parse_listen) ||
5753 !cfg_register_section("defaults", cfg_parse_listen) ||
5754 !cfg_register_section("global", cfg_parse_global) ||
5755 !cfg_register_section("userlist", cfg_parse_users) ||
5756 !cfg_register_section("peers", cfg_parse_peers))
5757 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 if ((f=fopen(file,"r")) == NULL)
5760 return -1;
5761
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005762 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005763 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005764 char *end;
5765 char *args[MAX_LINE_ARGS + 1];
5766 char *line = thisline;
5767
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 linenum++;
5769
5770 end = line + strlen(line);
5771
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005772 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5773 /* Check if we reached the limit and the last char is not \n.
5774 * Watch out for the last line without the terminating '\n'!
5775 */
5776 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005777 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005778 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005779 }
5780
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005782 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 line++;
5784
5785 arg = 0;
5786 args[arg] = line;
5787
5788 while (*line && arg < MAX_LINE_ARGS) {
5789 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5790 * C equivalent value. Other combinations left unchanged (eg: \1).
5791 */
5792 if (*line == '\\') {
5793 int skip = 0;
5794 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5795 *line = line[1];
5796 skip = 1;
5797 }
5798 else if (line[1] == 'r') {
5799 *line = '\r';
5800 skip = 1;
5801 }
5802 else if (line[1] == 'n') {
5803 *line = '\n';
5804 skip = 1;
5805 }
5806 else if (line[1] == 't') {
5807 *line = '\t';
5808 skip = 1;
5809 }
5810 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005811 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 unsigned char hex1, hex2;
5813 hex1 = toupper(line[2]) - '0';
5814 hex2 = toupper(line[3]) - '0';
5815 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5816 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5817 *line = (hex1<<4) + hex2;
5818 skip = 3;
5819 }
5820 else {
5821 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 }
5824 }
5825 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005826 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 end -= skip;
5828 }
5829 line++;
5830 }
5831 else if (*line == '#' || *line == '\n' || *line == '\r') {
5832 /* end of string, end of loop */
5833 *line = 0;
5834 break;
5835 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005836 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005838 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005839 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 line++;
5841 args[++arg] = line;
5842 }
5843 else {
5844 line++;
5845 }
5846 }
5847
5848 /* empty line */
5849 if (!**args)
5850 continue;
5851
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005852 if (*line) {
5853 /* we had to stop due to too many args.
5854 * Let's terminate the string, print the offending part then cut the
5855 * last arg.
5856 */
5857 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5858 line++;
5859 *line = '\0';
5860
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005861 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005862 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005863 err_code |= ERR_ALERT | ERR_FATAL;
5864 args[arg] = line;
5865 }
5866
Willy Tarreau540abe42007-05-02 20:50:16 +02005867 /* zero out remaining args and ensure that at least one entry
5868 * is zeroed out.
5869 */
5870 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871 args[arg] = line;
5872 }
5873
Willy Tarreau3842f002009-06-14 11:39:52 +02005874 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005875 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005876 char *tmp;
5877
Willy Tarreau3842f002009-06-14 11:39:52 +02005878 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005879 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005880 for (arg=0; *args[arg+1]; arg++)
5881 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005882 *tmp = '\0'; // fix the next arg to \0
5883 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005884 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005885 else if (!strcmp(args[0], "default")) {
5886 kwm = KWM_DEF;
5887 for (arg=0; *args[arg+1]; arg++)
5888 args[arg] = args[arg+1]; // shift args after inversion
5889 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005890
William Lallemand0f99e342011-10-12 17:50:54 +02005891 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5892 strcmp(args[0], "log") != 0) {
5893 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005894 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005895 }
5896
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005897 /* detect section start */
5898 list_for_each_entry(ics, &sections, list) {
5899 if (strcmp(args[0], ics->section_name) == 0) {
5900 cursection = ics->section_name;
5901 cs = ics;
5902 break;
5903 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005904 }
5905
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005907 if (cs)
5908 err_code |= cs->section_parser(file, linenum, args, kwm);
5909 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005910 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005911 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005913
5914 if (err_code & ERR_ABORT)
5915 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005917 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005919 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005920}
5921
Willy Tarreaubb925012009-07-23 13:36:36 +02005922/*
5923 * Returns the error code, 0 if OK, or any combination of :
5924 * - ERR_ABORT: must abort ASAP
5925 * - ERR_FATAL: we can continue parsing but not start the service
5926 * - ERR_WARN: a warning has been emitted
5927 * - ERR_ALERT: an alert has been emitted
5928 * Only the two first ones can stop processing, the two others are just
5929 * indicators.
5930 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005931int check_config_validity()
5932{
5933 int cfgerr = 0;
5934 struct proxy *curproxy = NULL;
5935 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005936 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005937 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005938 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005940 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 /*
5942 * Now, check for the integrity of all that we have collected.
5943 */
5944
5945 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005946 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947
Willy Tarreau193b8c62012-11-22 00:17:38 +01005948 if (!global.tune.max_http_hdr)
5949 global.tune.max_http_hdr = MAX_HTTP_HDR;
5950
5951 if (!global.tune.cookie_len)
5952 global.tune.cookie_len = CAPTURE_LEN;
5953
5954 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5955
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005956 /* Post initialisation of the users and groups lists. */
5957 err_code = userlist_postinit();
5958 if (err_code != ERR_NONE)
5959 goto out;
5960
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005961 /* first, we will invert the proxy list order */
5962 curproxy = NULL;
5963 while (proxy) {
5964 struct proxy *next;
5965
5966 next = proxy->next;
5967 proxy->next = curproxy;
5968 curproxy = proxy;
5969 if (!next)
5970 break;
5971 proxy = next;
5972 }
5973
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005975 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005976 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005977 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005978 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005979 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005980 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005981 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005982
Willy Tarreau050536d2012-10-04 08:47:34 +02005983 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005984 /* proxy ID not set, use automatic numbering with first
5985 * spare entry starting with next_pxid.
5986 */
5987 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5988 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5989 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005990 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005991 next_pxid++;
5992
Willy Tarreau55ea7572007-06-17 19:56:27 +02005993
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005995 /* ensure we don't keep listeners uselessly bound */
5996 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 curproxy = curproxy->next;
5998 continue;
5999 }
6000
Willy Tarreau102df612014-05-07 23:56:38 +02006001 /* Check multi-process mode compatibility for the current proxy */
6002
6003 if (curproxy->bind_proc) {
6004 /* an explicit bind-process was specified, let's check how many
6005 * processes remain.
6006 */
6007 nbproc = popcount(curproxy->bind_proc);
6008
6009 curproxy->bind_proc &= nbits(global.nbproc);
6010 if (!curproxy->bind_proc && nbproc == 1) {
6011 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);
6012 curproxy->bind_proc = 1;
6013 }
6014 else if (!curproxy->bind_proc && nbproc > 1) {
6015 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);
6016 curproxy->bind_proc = 0;
6017 }
6018 }
6019
Willy Tarreau3d209582014-05-09 17:06:11 +02006020 /* check and reduce the bind-proc of each listener */
6021 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6022 unsigned long mask;
6023
6024 if (!bind_conf->bind_proc)
6025 continue;
6026
6027 mask = nbits(global.nbproc);
6028 if (curproxy->bind_proc)
6029 mask &= curproxy->bind_proc;
6030 /* mask cannot be null here thanks to the previous checks */
6031
6032 nbproc = popcount(bind_conf->bind_proc);
6033 bind_conf->bind_proc &= mask;
6034
6035 if (!bind_conf->bind_proc && nbproc == 1) {
6036 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",
6037 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6038 bind_conf->bind_proc = mask & ~(mask - 1);
6039 }
6040 else if (!bind_conf->bind_proc && nbproc > 1) {
6041 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",
6042 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6043 bind_conf->bind_proc = 0;
6044 }
6045 }
6046
Willy Tarreau102df612014-05-07 23:56:38 +02006047 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
6048 * We now check how many processes the proxy will effectively run on.
6049 */
6050
6051 nbproc = global.nbproc;
6052 if (curproxy->bind_proc)
6053 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6054
6055 if (global.nbproc > 1 && curproxy->table.peers.name) {
6056 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6057 curproxy->id);
6058 cfgerr++;
6059 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006060
Willy Tarreauff01a212009-03-15 13:46:16 +01006061 switch (curproxy->mode) {
6062 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006063 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006064 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006065 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6066 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006067 cfgerr++;
6068 }
6069
6070 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006071 Warning("config : servers will be ignored for %s '%s'.\n",
6072 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006073 break;
6074
6075 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006076 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006077 break;
6078
6079 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006080 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006081 break;
6082 }
6083
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006084 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006085 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006086 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006087 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6088 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006089 cfgerr++;
6090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006092 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006093 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6094 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006095 cfgerr++;
6096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006098 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006099 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6100 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006101 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006102 }
6103 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006104 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006105 /* If no LB algo is set in a backend, and we're not in
6106 * transparent mode, dispatch mode nor proxy mode, we
6107 * want to use balance roundrobin by default.
6108 */
6109 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6110 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006111 }
6112 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006113
Willy Tarreau1620ec32011-08-06 17:05:02 +02006114 if (curproxy->options & PR_O_DISPATCH)
6115 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6116 else if (curproxy->options & PR_O_HTTP_PROXY)
6117 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6118 else if (curproxy->options & PR_O_TRANSP)
6119 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006120
Willy Tarreau1620ec32011-08-06 17:05:02 +02006121 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6122 if (curproxy->options & PR_O_DISABLE404) {
6123 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6124 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6125 err_code |= ERR_WARN;
6126 curproxy->options &= ~PR_O_DISABLE404;
6127 }
6128 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6129 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6130 "send-state", proxy_type_str(curproxy), curproxy->id);
6131 err_code |= ERR_WARN;
6132 curproxy->options &= ~PR_O2_CHK_SNDST;
6133 }
Willy Tarreauef781042010-01-27 11:53:01 +01006134 }
6135
Simon Horman98637e52014-06-20 12:30:16 +09006136 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6137 if (!global.external_check) {
6138 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6139 curproxy->id, "option external-check");
6140 cfgerr++;
6141 }
6142 if (!curproxy->check_command) {
6143 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6144 curproxy->id, "option external-check");
6145 cfgerr++;
6146 }
6147 }
6148
6149 if (curproxy->check_command) {
6150 int clear = 0;
6151 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6152 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6153 "external-check command", proxy_type_str(curproxy), curproxy->id);
6154 err_code |= ERR_WARN;
6155 clear = 1;
6156 }
6157 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6158 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6159 curproxy->id, "external-check command");
6160 cfgerr++;
6161 }
6162 if (clear) {
6163 free(curproxy->check_command);
6164 curproxy->check_command = NULL;
6165 }
6166 }
6167
6168 if (curproxy->check_path) {
6169 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6170 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6171 "external-check path", proxy_type_str(curproxy), curproxy->id);
6172 err_code |= ERR_WARN;
6173 free(curproxy->check_path);
6174 curproxy->check_path = NULL;
6175 }
6176 }
6177
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006178 /* if a default backend was specified, let's find it */
6179 if (curproxy->defbe.name) {
6180 struct proxy *target;
6181
Alex Williams96532db2009-11-01 21:27:13 -05006182 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006183 if (!target) {
6184 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6185 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006186 cfgerr++;
6187 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006188 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6189 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006190 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006191 } else {
6192 free(curproxy->defbe.name);
6193 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006194 /* we force the backend to be present on at least all of
6195 * the frontend's processes.
6196 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006197 if (target->bind_proc)
6198 target->bind_proc = curproxy->bind_proc ?
6199 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006200
6201 /* Emit a warning if this proxy also has some servers */
6202 if (curproxy->srv) {
6203 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6204 curproxy->id);
6205 err_code |= ERR_WARN;
6206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 }
6208 }
6209
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006210 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006211 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6212 /* map jump target for ACT_SETBE in req_rep chain */
6213 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006214 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006215 struct proxy *target;
6216
Willy Tarreaua496b602006-12-17 23:15:24 +01006217 if (exp->action != ACT_SETBE)
6218 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006219
Alex Williams96532db2009-11-01 21:27:13 -05006220 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006221 if (!target) {
6222 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6223 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006224 cfgerr++;
6225 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006226 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6227 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006228 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006229 } else {
6230 free((void *)exp->replace);
6231 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006232 /* we force the backend to be present on at least all of
6233 * the frontend's processes.
6234 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006235 if (target->bind_proc)
6236 target->bind_proc = curproxy->bind_proc ?
6237 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006238 }
6239 }
6240 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006241
6242 /* find the target proxy for 'use_backend' rules */
6243 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006244 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006245 struct logformat_node *node;
6246 char *pxname;
6247
6248 /* Try to parse the string as a log format expression. If the result
6249 * of the parsing is only one entry containing a simple string, then
6250 * it's a standard string corresponding to a static rule, thus the
6251 * parsing is cancelled and be.name is restored to be resolved.
6252 */
6253 pxname = rule->be.name;
6254 LIST_INIT(&rule->be.expr);
6255 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6256 curproxy->conf.args.file, curproxy->conf.args.line);
6257 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6258
6259 if (!LIST_ISEMPTY(&rule->be.expr)) {
6260 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6261 rule->dynamic = 1;
6262 free(pxname);
6263 continue;
6264 }
6265 /* simple string: free the expression and fall back to static rule */
6266 free(node->arg);
6267 free(node);
6268 }
6269
6270 rule->dynamic = 0;
6271 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006272
Alex Williams96532db2009-11-01 21:27:13 -05006273 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006274
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006275 if (!target) {
6276 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6277 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006278 cfgerr++;
6279 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006280 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6281 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006282 cfgerr++;
6283 } else {
6284 free((void *)rule->be.name);
6285 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006286 /* we force the backend to be present on at least all of
6287 * the frontend's processes.
6288 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006289 if (target->bind_proc)
6290 target->bind_proc = curproxy->bind_proc ?
6291 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006292 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006293 }
6294
6295 /* find the target proxy for 'use_backend' rules */
6296 list_for_each_entry(srule, &curproxy->server_rules, list) {
6297 struct server *target = findserver(curproxy, srule->srv.name);
6298
6299 if (!target) {
6300 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6301 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6302 cfgerr++;
6303 continue;
6304 }
6305 free((void *)srule->srv.name);
6306 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006307 }
6308
Emeric Brunb982a3d2010-01-04 15:45:53 +01006309 /* find the target table for 'stick' rules */
6310 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6311 struct proxy *target;
6312
Emeric Brun1d33b292010-01-04 15:47:17 +01006313 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6314 if (mrule->flags & STK_IS_STORE)
6315 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6316
Emeric Brunb982a3d2010-01-04 15:45:53 +01006317 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006318 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006319 else
6320 target = curproxy;
6321
6322 if (!target) {
6323 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6324 curproxy->id, mrule->table.name);
6325 cfgerr++;
6326 }
6327 else if (target->table.size == 0) {
6328 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6329 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6330 cfgerr++;
6331 }
Willy Tarreau12785782012-04-27 21:37:17 +02006332 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6333 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006334 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6335 cfgerr++;
6336 }
6337 else {
6338 free((void *)mrule->table.name);
6339 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006340 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006341 }
6342 }
6343
6344 /* find the target table for 'store response' rules */
6345 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6346 struct proxy *target;
6347
Emeric Brun1d33b292010-01-04 15:47:17 +01006348 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6349
Emeric Brunb982a3d2010-01-04 15:45:53 +01006350 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006351 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006352 else
6353 target = curproxy;
6354
6355 if (!target) {
6356 Alert("Proxy '%s': unable to find store table '%s'.\n",
6357 curproxy->id, mrule->table.name);
6358 cfgerr++;
6359 }
6360 else if (target->table.size == 0) {
6361 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6362 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6363 cfgerr++;
6364 }
Willy Tarreau12785782012-04-27 21:37:17 +02006365 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6366 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006367 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6368 cfgerr++;
6369 }
6370 else {
6371 free((void *)mrule->table.name);
6372 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006373 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006374 }
6375 }
6376
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006377 /* find the target table for 'tcp-request' layer 4 rules */
6378 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6379 struct proxy *target;
6380
Willy Tarreaub4c84932013-07-23 19:15:30 +02006381 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006382 continue;
6383
6384 if (trule->act_prm.trk_ctr.table.n)
6385 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6386 else
6387 target = curproxy;
6388
6389 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006390 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6391 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006392 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006393 cfgerr++;
6394 }
6395 else if (target->table.size == 0) {
6396 Alert("Proxy '%s': table '%s' used but not configured.\n",
6397 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6398 cfgerr++;
6399 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006400 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6401 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6402 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 +01006403 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006404 cfgerr++;
6405 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006406 else {
6407 free(trule->act_prm.trk_ctr.table.n);
6408 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006409 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006410 * to pass a list of counters to track and allocate them right here using
6411 * stktable_alloc_data_type().
6412 */
6413 }
6414 }
6415
Willy Tarreaud1f96522010-08-03 19:34:32 +02006416 /* find the target table for 'tcp-request' layer 6 rules */
6417 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6418 struct proxy *target;
6419
Willy Tarreaub4c84932013-07-23 19:15:30 +02006420 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006421 continue;
6422
6423 if (trule->act_prm.trk_ctr.table.n)
6424 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6425 else
6426 target = curproxy;
6427
6428 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006429 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6430 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006431 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006432 cfgerr++;
6433 }
6434 else if (target->table.size == 0) {
6435 Alert("Proxy '%s': table '%s' used but not configured.\n",
6436 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6437 cfgerr++;
6438 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006439 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6440 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6441 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 +01006442 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006443 cfgerr++;
6444 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006445 else {
6446 free(trule->act_prm.trk_ctr.table.n);
6447 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006448 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006449 * to pass a list of counters to track and allocate them right here using
6450 * stktable_alloc_data_type().
6451 */
6452 }
6453 }
6454
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006455 /* move any "block" rules at the beginning of the http-request rules */
6456 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6457 /* insert block_rules into http_req_rules at the beginning */
6458 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6459 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6460 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6461 curproxy->http_req_rules.n = curproxy->block_rules.n;
6462 LIST_INIT(&curproxy->block_rules);
6463 }
6464
Emeric Brun32da3c42010-09-23 18:39:19 +02006465 if (curproxy->table.peers.name) {
6466 struct peers *curpeers = peers;
6467
6468 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6469 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6470 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006471 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006472 break;
6473 }
6474 }
6475
6476 if (!curpeers) {
6477 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6478 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006479 free((void *)curproxy->table.peers.name);
6480 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006481 cfgerr++;
6482 }
6483 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006484 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6485 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006486 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006487 cfgerr++;
6488 }
6489 }
6490
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006491 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006492 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006493 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6494 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6495 "proxy", curproxy->id);
6496 cfgerr++;
6497 goto out_uri_auth_compat;
6498 }
6499
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006500 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006501 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006502 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006503 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006504
Willy Tarreau95fa4692010-02-01 13:05:50 +01006505 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6506 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006507
6508 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006509 uri_auth_compat_req[i++] = "realm";
6510 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6511 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006512
Willy Tarreau95fa4692010-02-01 13:05:50 +01006513 uri_auth_compat_req[i++] = "unless";
6514 uri_auth_compat_req[i++] = "{";
6515 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6516 uri_auth_compat_req[i++] = "}";
6517 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006518
Willy Tarreauff011f22011-01-06 17:51:27 +01006519 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6520 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006521 cfgerr++;
6522 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006523 }
6524
Willy Tarreauff011f22011-01-06 17:51:27 +01006525 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006526
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006527 if (curproxy->uri_auth->auth_realm) {
6528 free(curproxy->uri_auth->auth_realm);
6529 curproxy->uri_auth->auth_realm = NULL;
6530 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006531
6532 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006533 }
6534out_uri_auth_compat:
6535
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006536 /* compile the log format */
6537 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006538 if (curproxy->conf.logformat_string != default_http_log_format &&
6539 curproxy->conf.logformat_string != default_tcp_log_format &&
6540 curproxy->conf.logformat_string != clf_http_log_format)
6541 free(curproxy->conf.logformat_string);
6542 curproxy->conf.logformat_string = NULL;
6543 free(curproxy->conf.lfs_file);
6544 curproxy->conf.lfs_file = NULL;
6545 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006546 }
6547
Willy Tarreau62a61232013-04-12 18:13:46 +02006548 if (curproxy->conf.logformat_string) {
6549 curproxy->conf.args.ctx = ARGC_LOG;
6550 curproxy->conf.args.file = curproxy->conf.lfs_file;
6551 curproxy->conf.args.line = curproxy->conf.lfs_line;
6552 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006553 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006554 curproxy->conf.args.file = NULL;
6555 curproxy->conf.args.line = 0;
6556 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006557
Willy Tarreau62a61232013-04-12 18:13:46 +02006558 if (curproxy->conf.uniqueid_format_string) {
6559 curproxy->conf.args.ctx = ARGC_UIF;
6560 curproxy->conf.args.file = curproxy->conf.uif_file;
6561 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006562 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006563 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6564 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006565 curproxy->conf.args.file = NULL;
6566 curproxy->conf.args.line = 0;
6567 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006568
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006569 /* only now we can check if some args remain unresolved.
6570 * This must be done after the users and groups resolution.
6571 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006572 cfgerr += smp_resolve_args(curproxy);
6573 if (!cfgerr)
6574 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006575
Willy Tarreau2738a142006-07-08 17:28:09 +02006576 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006577 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006578 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006579 (!curproxy->timeout.connect ||
6580 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006581 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006582 " | While not properly invalid, you will certainly encounter various problems\n"
6583 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006584 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006585 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006586 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006587 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006588
Willy Tarreau1fa31262007-12-03 00:36:16 +01006589 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6590 * We must still support older configurations, so let's find out whether those
6591 * parameters have been set or must be copied from contimeouts.
6592 */
6593 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006594 if (!curproxy->timeout.tarpit ||
6595 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006596 /* tarpit timeout not set. We search in the following order:
6597 * default.tarpit, curr.connect, default.connect.
6598 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006599 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006600 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006601 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006602 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006603 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006604 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006605 }
6606 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006607 (!curproxy->timeout.queue ||
6608 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006609 /* queue timeout not set. We search in the following order:
6610 * default.queue, curr.connect, default.connect.
6611 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006612 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006613 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006614 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006615 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006616 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006617 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006618 }
6619 }
6620
Willy Tarreau1620ec32011-08-06 17:05:02 +02006621 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006622 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6623 curproxy->check_req = (char *)malloc(curproxy->check_len);
6624 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006625 }
6626
Willy Tarreau215663d2014-06-13 18:30:23 +02006627 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6628 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6629 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6630 proxy_type_str(curproxy), curproxy->id);
6631 err_code |= ERR_WARN;
6632 }
6633
Willy Tarreau193b8c62012-11-22 00:17:38 +01006634 /* ensure that cookie capture length is not too large */
6635 if (curproxy->capture_len >= global.tune.cookie_len) {
6636 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6637 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6638 err_code |= ERR_WARN;
6639 curproxy->capture_len = global.tune.cookie_len - 1;
6640 }
6641
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006642 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006643 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006644 curproxy->req_cap_pool = create_pool("ptrcap",
6645 curproxy->nb_req_cap * sizeof(char *),
6646 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006647 }
6648
6649 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006650 curproxy->rsp_cap_pool = create_pool("ptrcap",
6651 curproxy->nb_rsp_cap * sizeof(char *),
6652 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006653 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006654
Willy Tarreaubaaee002006-06-26 02:48:02 +02006655 /* first, we will invert the servers list order */
6656 newsrv = NULL;
6657 while (curproxy->srv) {
6658 struct server *next;
6659
6660 next = curproxy->srv->next;
6661 curproxy->srv->next = newsrv;
6662 newsrv = curproxy->srv;
6663 if (!next)
6664 break;
6665 curproxy->srv = next;
6666 }
6667
Willy Tarreau17edc812014-01-03 12:14:34 +01006668 /* Check that no server name conflicts. This causes trouble in the stats.
6669 * We only emit a warning for the first conflict affecting each server,
6670 * in order to avoid combinatory explosion if all servers have the same
6671 * name. We do that only for servers which do not have an explicit ID,
6672 * because these IDs were made also for distinguishing them and we don't
6673 * want to annoy people who correctly manage them.
6674 */
6675 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6676 struct server *other_srv;
6677
6678 if (newsrv->puid)
6679 continue;
6680
6681 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6682 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6683 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6684 newsrv->conf.file, newsrv->conf.line,
6685 proxy_type_str(curproxy), curproxy->id,
6686 newsrv->id, other_srv->conf.line);
6687 break;
6688 }
6689 }
6690 }
6691
Willy Tarreaudd701652010-05-25 23:03:02 +02006692 /* assign automatic UIDs to servers which don't have one yet */
6693 next_id = 1;
6694 newsrv = curproxy->srv;
6695 while (newsrv != NULL) {
6696 if (!newsrv->puid) {
6697 /* server ID not set, use automatic numbering with first
6698 * spare entry starting with next_svid.
6699 */
6700 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6701 newsrv->conf.id.key = newsrv->puid = next_id;
6702 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6703 }
6704 next_id++;
6705 newsrv = newsrv->next;
6706 }
6707
Willy Tarreau20697042007-11-15 23:26:18 +01006708 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006709 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710
Willy Tarreau62c3be22012-01-20 13:12:32 +01006711 /*
6712 * If this server supports a maxconn parameter, it needs a dedicated
6713 * tasks to fill the emptied slots when a connection leaves.
6714 * Also, resolve deferred tracking dependency if needed.
6715 */
6716 newsrv = curproxy->srv;
6717 while (newsrv != NULL) {
6718 if (newsrv->minconn > newsrv->maxconn) {
6719 /* Only 'minconn' was specified, or it was higher than or equal
6720 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6721 * this will avoid further useless expensive computations.
6722 */
6723 newsrv->maxconn = newsrv->minconn;
6724 } else if (newsrv->maxconn && !newsrv->minconn) {
6725 /* minconn was not specified, so we set it to maxconn */
6726 newsrv->minconn = newsrv->maxconn;
6727 }
6728
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006729#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006730 if (newsrv->use_ssl || newsrv->check.use_ssl)
6731 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006732#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006733
Willy Tarreau2f075e92013-12-03 11:11:34 +01006734 /* set the check type on the server */
6735 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6736
Willy Tarreau62c3be22012-01-20 13:12:32 +01006737 if (newsrv->trackit) {
6738 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006739 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006740 char *pname, *sname;
6741
6742 pname = newsrv->trackit;
6743 sname = strrchr(pname, '/');
6744
6745 if (sname)
6746 *sname++ = '\0';
6747 else {
6748 sname = pname;
6749 pname = NULL;
6750 }
6751
6752 if (pname) {
6753 px = findproxy(pname, PR_CAP_BE);
6754 if (!px) {
6755 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6756 proxy_type_str(curproxy), curproxy->id,
6757 newsrv->id, pname);
6758 cfgerr++;
6759 goto next_srv;
6760 }
6761 } else
6762 px = curproxy;
6763
6764 srv = findserver(px, sname);
6765 if (!srv) {
6766 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6767 proxy_type_str(curproxy), curproxy->id,
6768 newsrv->id, sname);
6769 cfgerr++;
6770 goto next_srv;
6771 }
6772
Willy Tarreau32091232014-05-16 13:52:00 +02006773 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6774 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6775 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006776 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006777 "tracking as it does not have any check nor agent enabled.\n",
6778 proxy_type_str(curproxy), curproxy->id,
6779 newsrv->id, px->id, srv->id);
6780 cfgerr++;
6781 goto next_srv;
6782 }
6783
6784 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6785
6786 if (loop) {
6787 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6788 "belongs to a tracking chain looping back to %s/%s.\n",
6789 proxy_type_str(curproxy), curproxy->id,
6790 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006791 cfgerr++;
6792 goto next_srv;
6793 }
6794
6795 if (curproxy != px &&
6796 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6797 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6798 "tracking: disable-on-404 option inconsistency.\n",
6799 proxy_type_str(curproxy), curproxy->id,
6800 newsrv->id, px->id, srv->id);
6801 cfgerr++;
6802 goto next_srv;
6803 }
6804
6805 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006806 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006807 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006808 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006809 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006810 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006811 }
6812
6813 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006814 newsrv->tracknext = srv->trackers;
6815 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006816
6817 free(newsrv->trackit);
6818 newsrv->trackit = NULL;
6819 }
6820 next_srv:
6821 newsrv = newsrv->next;
6822 }
6823
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006824 /* We have to initialize the server lookup mechanism depending
6825 * on what LB algorithm was choosen.
6826 */
6827
6828 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6829 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6830 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006831 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6832 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6833 init_server_map(curproxy);
6834 } else {
6835 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6836 fwrr_init_server_groups(curproxy);
6837 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006838 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006839
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006840 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006841 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6842 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6843 fwlc_init_server_tree(curproxy);
6844 } else {
6845 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6846 fas_init_server_tree(curproxy);
6847 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006848 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006849
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006850 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006851 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6852 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6853 chash_init_server_tree(curproxy);
6854 } else {
6855 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6856 init_server_map(curproxy);
6857 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006858 break;
6859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006860
6861 if (curproxy->options & PR_O_LOGASAP)
6862 curproxy->to_log &= ~LW_BYTES;
6863
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006864 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006865 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006866 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6867 proxy_type_str(curproxy), curproxy->id);
6868 err_code |= ERR_WARN;
6869 }
6870
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006871 if (curproxy->mode != PR_MODE_HTTP) {
6872 int optnum;
6873
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006874 if (curproxy->uri_auth) {
6875 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6876 proxy_type_str(curproxy), curproxy->id);
6877 err_code |= ERR_WARN;
6878 curproxy->uri_auth = NULL;
6879 }
6880
Willy Tarreau87cf5142011-08-19 22:57:24 +02006881 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006882 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6883 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6884 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006885 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006886 }
6887
6888 if (curproxy->options & PR_O_ORGTO) {
6889 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6890 "originalto", proxy_type_str(curproxy), curproxy->id);
6891 err_code |= ERR_WARN;
6892 curproxy->options &= ~PR_O_ORGTO;
6893 }
6894
6895 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6896 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6897 (curproxy->cap & cfg_opts[optnum].cap) &&
6898 (curproxy->options & cfg_opts[optnum].val)) {
6899 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6900 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6901 err_code |= ERR_WARN;
6902 curproxy->options &= ~cfg_opts[optnum].val;
6903 }
6904 }
6905
6906 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6907 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6908 (curproxy->cap & cfg_opts2[optnum].cap) &&
6909 (curproxy->options2 & cfg_opts2[optnum].val)) {
6910 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6911 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6912 err_code |= ERR_WARN;
6913 curproxy->options2 &= ~cfg_opts2[optnum].val;
6914 }
6915 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006916
Pieter Baauwd551fb52013-05-08 22:49:23 +02006917#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006918 if (curproxy->conn_src.bind_hdr_occ) {
6919 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006920 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006921 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006922 err_code |= ERR_WARN;
6923 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006924#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006925 }
6926
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006928 * ensure that we're not cross-dressing a TCP server into HTTP.
6929 */
6930 newsrv = curproxy->srv;
6931 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006932 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006933 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6934 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006935 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006936 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006937
Willy Tarreau0cec3312011-10-31 13:49:26 +01006938 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6939 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6940 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6941 err_code |= ERR_WARN;
6942 }
6943
Willy Tarreauc93cd162014-05-13 15:54:22 +02006944 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006945 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6946 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6947 err_code |= ERR_WARN;
6948 }
6949
Pieter Baauwd551fb52013-05-08 22:49:23 +02006950#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006951 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6952 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006953 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 +01006954 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006955 err_code |= ERR_WARN;
6956 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006957#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006958 newsrv = newsrv->next;
6959 }
6960
Willy Tarreauc1a21672009-08-16 22:37:44 +02006961 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006962 if (!curproxy->accept)
6963 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006964
Willy Tarreauc1a21672009-08-16 22:37:44 +02006965 if (curproxy->tcp_req.inspect_delay ||
6966 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006967 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006968
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006969 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006970 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006971 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006972 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006973
6974 /* both TCP and HTTP must check switching rules */
6975 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6976 }
6977
6978 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006979 if (curproxy->tcp_req.inspect_delay ||
6980 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6981 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6982
Emeric Brun97679e72010-09-23 17:56:44 +02006983 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6984 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6985
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006986 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006987 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006988 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006989 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006990
6991 /* If the backend does requires RDP cookie persistence, we have to
6992 * enable the corresponding analyser.
6993 */
6994 if (curproxy->options2 & PR_O2_RDPC_PRST)
6995 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6996 }
6997
Emeric Brunc52962f2012-11-15 18:28:02 +01006998#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006999 /* Configure SSL for each bind line.
7000 * Note: if configuration fails at some point, the ->ctx member
7001 * remains NULL so that listeners can later detach.
7002 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007003 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007004 int alloc_ctx;
7005
Emeric Brunc52962f2012-11-15 18:28:02 +01007006 if (!bind_conf->is_ssl) {
7007 if (bind_conf->default_ctx) {
7008 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7009 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7010 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007011 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007012 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007013 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007014 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007015 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007016 cfgerr++;
7017 continue;
7018 }
7019
Emeric Brun8dc60392014-05-09 13:52:00 +02007020 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007021 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007022 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7023 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");
7024 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007025 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007026 cfgerr++;
7027 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007028 }
7029
Emeric Brunfc0421f2012-09-07 17:30:07 +02007030 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007031 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007032 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007033#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007034
Willy Tarreaue6b98942007-10-29 01:09:36 +01007035 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007036 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007037 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007038 if (!listener->luid) {
7039 /* listener ID not set, use automatic numbering with first
7040 * spare entry starting with next_luid.
7041 */
7042 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7043 listener->conf.id.key = listener->luid = next_id;
7044 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007045 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007046 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007047
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007048 /* enable separate counters */
7049 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7050 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007051 if (!listener->name)
7052 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007053 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007054
Willy Tarreaue6b98942007-10-29 01:09:36 +01007055 if (curproxy->options & PR_O_TCP_NOLING)
7056 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007057 if (!listener->maxconn)
7058 listener->maxconn = curproxy->maxconn;
7059 if (!listener->backlog)
7060 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007061 if (!listener->maxaccept)
7062 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7063
7064 /* we want to have an optimal behaviour on single process mode to
7065 * maximize the work at once, but in multi-process we want to keep
7066 * some fairness between processes, so we target half of the max
7067 * number of events to be balanced over all the processes the proxy
7068 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7069 * used to disable the limit.
7070 */
7071 if (listener->maxaccept > 0) {
7072 if (nbproc > 1)
7073 listener->maxaccept = (listener->maxaccept + 1) / 2;
7074 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7075 }
7076
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007077 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007078 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007079 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007080 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007081
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007082 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7083 listener->options |= LI_O_TCP_RULES;
7084
Willy Tarreaude3041d2010-05-31 10:56:17 +02007085 if (curproxy->mon_mask.s_addr)
7086 listener->options |= LI_O_CHK_MONNET;
7087
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007088 /* smart accept mode is automatic in HTTP mode */
7089 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007090 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007091 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7092 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007093 }
7094
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007095 /* Release unused SSL configs */
7096 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7097 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007098 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007099#ifdef USE_OPENSSL
7100 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007101 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007102 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007103 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007104 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007105#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007106 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007107
Willy Tarreau102df612014-05-07 23:56:38 +02007108 if (nbproc > 1) {
7109 if (curproxy->uri_auth) {
7110 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7111 curproxy->id);
7112 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7113 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7114 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007115 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007116 }
Willy Tarreau102df612014-05-07 23:56:38 +02007117 if (curproxy->appsession_name) {
7118 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7119 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007120 }
Willy Tarreau102df612014-05-07 23:56:38 +02007121 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7122 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7123 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007124 }
7125 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007126
7127 /* create the task associated with the proxy */
7128 curproxy->task = task_new();
7129 if (curproxy->task) {
7130 curproxy->task->context = curproxy;
7131 curproxy->task->process = manage_proxy;
7132 /* no need to queue, it will be done automatically if some
7133 * listener gets limited.
7134 */
7135 curproxy->task->expire = TICK_ETERNITY;
7136 } else {
7137 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7138 curproxy->id);
7139 cfgerr++;
7140 }
7141
Willy Tarreaubaaee002006-06-26 02:48:02 +02007142 curproxy = curproxy->next;
7143 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007144
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007145 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007146 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007147 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7148 unsigned long mask;
7149
7150 mask = nbits(global.nbproc);
7151 if (global.stats_fe->bind_proc)
7152 mask &= global.stats_fe->bind_proc;
7153
7154 if (bind_conf->bind_proc)
7155 mask &= bind_conf->bind_proc;
7156
7157 /* stop here if more than one process is used */
7158 if (popcount(mask) > 1)
7159 break;
7160 }
7161 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7162 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 +01007163 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007164 }
7165
7166 /* automatically compute fullconn if not set. We must not do it in the
7167 * loop above because cross-references are not yet fully resolved.
7168 */
7169 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7170 /* If <fullconn> is not set, let's set it to 10% of the sum of
7171 * the possible incoming frontend's maxconns.
7172 */
7173 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7174 struct proxy *fe;
7175 int total = 0;
7176
7177 /* sum up the number of maxconns of frontends which
7178 * reference this backend at least once or which are
7179 * the same one ('listen').
7180 */
7181 for (fe = proxy; fe; fe = fe->next) {
7182 struct switching_rule *rule;
7183 struct hdr_exp *exp;
7184 int found = 0;
7185
7186 if (!(fe->cap & PR_CAP_FE))
7187 continue;
7188
7189 if (fe == curproxy) /* we're on a "listen" instance */
7190 found = 1;
7191
7192 if (fe->defbe.be == curproxy) /* "default_backend" */
7193 found = 1;
7194
7195 /* check if a "use_backend" rule matches */
7196 if (!found) {
7197 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007198 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007199 found = 1;
7200 break;
7201 }
7202 }
7203 }
7204
7205 /* check if a "reqsetbe" rule matches */
7206 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7207 if (exp->action == ACT_SETBE &&
7208 (struct proxy *)exp->replace == curproxy) {
7209 found = 1;
7210 break;
7211 }
7212 }
7213
7214 /* now we've checked all possible ways to reference a backend
7215 * from a frontend.
7216 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007217 if (!found)
7218 continue;
7219 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007220 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007221 /* we have the sum of the maxconns in <total>. We only
7222 * keep 10% of that sum to set the default fullconn, with
7223 * a hard minimum of 1 (to avoid a divide by zero).
7224 */
7225 curproxy->fullconn = (total + 9) / 10;
7226 if (!curproxy->fullconn)
7227 curproxy->fullconn = 1;
7228 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007229 }
7230
Willy Tarreau056f5682010-06-06 15:51:11 +02007231 /* initialize stick-tables on backend capable proxies. This must not
7232 * be done earlier because the data size may be discovered while parsing
7233 * other proxies.
7234 */
Godbach9703e662013-12-11 21:11:41 +08007235 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007236 if (curproxy->state == PR_STSTOPPED)
7237 continue;
7238
Godbach9703e662013-12-11 21:11:41 +08007239 if (!stktable_init(&curproxy->table)) {
7240 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7241 cfgerr++;
7242 }
7243 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007244
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007245 /*
7246 * Recount currently required checks.
7247 */
7248
7249 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7250 int optnum;
7251
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007252 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7253 if (curproxy->options & cfg_opts[optnum].val)
7254 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007255
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007256 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7257 if (curproxy->options2 & cfg_opts2[optnum].val)
7258 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007259 }
7260
Willy Tarreau122541c2011-09-07 21:24:49 +02007261 if (peers) {
7262 struct peers *curpeers = peers, **last;
7263 struct peer *p, *pb;
7264
7265 /* Remove all peers sections which don't have a valid listener.
7266 * This can happen when a peers section is never referenced and
7267 * does not contain a local peer.
7268 */
7269 last = &peers;
7270 while (*last) {
7271 curpeers = *last;
7272 if (curpeers->peers_fe) {
7273 last = &curpeers->next;
7274 continue;
7275 }
7276
7277 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7278 curpeers->id, localpeer);
7279
7280 p = curpeers->remote;
7281 while (p) {
7282 pb = p->next;
7283 free(p->id);
7284 free(p);
7285 p = pb;
7286 }
7287
7288 /* Destroy and unlink this curpeers section.
7289 * Note: curpeers is backed up into *last.
7290 */
7291 free(curpeers->id);
7292 curpeers = curpeers->next;
7293 free(*last);
7294 *last = curpeers;
7295 }
7296 }
7297
Willy Tarreau34eb6712011-10-24 18:15:04 +02007298 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007299 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007300 MEM_F_SHARED);
7301
Willy Tarreaubb925012009-07-23 13:36:36 +02007302 if (cfgerr > 0)
7303 err_code |= ERR_ALERT | ERR_FATAL;
7304 out:
7305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007306}
7307
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007308/*
7309 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7310 * parsing sessions.
7311 */
7312void cfg_register_keywords(struct cfg_kw_list *kwl)
7313{
7314 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7315}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007316
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007317/*
7318 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7319 */
7320void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7321{
7322 LIST_DEL(&kwl->list);
7323 LIST_INIT(&kwl->list);
7324}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007325
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007326/* this function register new section in the haproxy configuration file.
7327 * <section_name> is the name of this new section and <section_parser>
7328 * is the called parser. If two section declaration have the same name,
7329 * only the first declared is used.
7330 */
7331int cfg_register_section(char *section_name,
7332 int (*section_parser)(const char *, int, char **, int))
7333{
7334 struct cfg_section *cs;
7335
7336 cs = calloc(1, sizeof(*cs));
7337 if (!cs) {
7338 Alert("register section '%s': out of memory.\n", section_name);
7339 return 0;
7340 }
7341
7342 cs->section_name = section_name;
7343 cs->section_parser = section_parser;
7344
7345 LIST_ADDQ(&sections, &cs->list);
7346
7347 return 1;
7348}
7349
Willy Tarreaubaaee002006-06-26 02:48:02 +02007350/*
7351 * Local variables:
7352 * c-indent-level: 8
7353 * c-basic-offset: 8
7354 * End:
7355 */