blob: 42c1790ce6386461e02ccc4d13dda3c96fd5e376 [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;
Willy Tarreau18324f52014-06-27 18:10:07 +02001260 int arg = 0;
1261 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001262
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 if (*(args[1]) == 0 || *(args[2]) == 0) {
1264 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
William Lallemand0f99e342011-10-12 17:50:54 +02001268
1269 logsrv = calloc(1, sizeof(struct logsrv));
1270
Willy Tarreau18324f52014-06-27 18:10:07 +02001271 /* just after the address, a length may be specified */
1272 if (strcmp(args[arg+2], "len") == 0) {
1273 len = atoi(args[arg+3]);
1274 if (len < 80 || len > 65535) {
1275 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1276 file, linenum, args[arg+3]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280 logsrv->maxlen = len;
1281
1282 /* skip these two args */
1283 arg += 2;
1284 }
1285 else
1286 logsrv->maxlen = MAX_SYSLOG_LEN;
1287
1288 if (logsrv->maxlen > global.max_syslog_len) {
1289 global.max_syslog_len = logsrv->maxlen;
1290 logline = realloc(logline, global.max_syslog_len + 1);
1291 }
1292
1293 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001294 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001295 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001297 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001298 }
1299
William Lallemand0f99e342011-10-12 17:50:54 +02001300 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001301 if (*(args[arg+3])) {
1302 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001303 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001304 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001306 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 }
1308 }
1309
William Lallemand0f99e342011-10-12 17:50:54 +02001310 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001311 if (*(args[arg+4])) {
1312 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001313 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001314 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001315 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001316 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001317 }
1318 }
1319
Willy Tarreau902636f2013-03-10 19:44:48 +01001320 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001321 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001322 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001323 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001324 free(logsrv);
1325 goto out;
1326 }
1327 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001328
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001329 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001330 if (port1 != port2) {
1331 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1332 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001333 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001334 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001335 goto out;
1336 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001337
William Lallemand0f99e342011-10-12 17:50:54 +02001338 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001339 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001340 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342
William Lallemand0f99e342011-10-12 17:50:54 +02001343 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001344 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001345 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1346 char *name;
1347 int len;
1348
1349 if (global.log_send_hostname != NULL) {
1350 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1351 err_code |= ERR_ALERT;
1352 goto out;
1353 }
1354
1355 if (*(args[1]))
1356 name = args[1];
1357 else
1358 name = hostname;
1359
1360 len = strlen(name);
1361
1362 /* We'll add a space after the name to respect the log format */
1363 free(global.log_send_hostname);
1364 global.log_send_hostname = malloc(len + 2);
1365 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1366 }
Kevinm48936af2010-12-22 16:08:21 +00001367 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1368 if (*(args[1]) == 0) {
1369 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto out;
1372 }
1373 free(global.log_tag);
1374 global.log_tag = strdup(args[1]);
1375 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001376 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1377 if (global.spread_checks != 0) {
1378 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001379 err_code |= ERR_ALERT;
1380 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001381 }
1382 if (*(args[1]) == 0) {
1383 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001384 err_code |= ERR_ALERT | ERR_FATAL;
1385 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001386 }
1387 global.spread_checks = atol(args[1]);
1388 if (global.spread_checks < 0 || global.spread_checks > 50) {
1389 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001393 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1394 const char *err;
1395 unsigned int val;
1396
1397
1398 if (*(args[1]) == 0) {
1399 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
1402 }
1403
1404 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1405 if (err) {
1406 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 }
1409 global.max_spread_checks = val;
1410 if (global.max_spread_checks < 0) {
1411 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 }
1414 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001415 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1416#ifdef USE_CPU_AFFINITY
1417 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001418 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001419 unsigned long cpus = 0;
1420
1421 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001422 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001423 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001424 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001425 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001426 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001427 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001428 proc = atol(args[1]);
1429 if (proc >= 1 && proc <= LONGBITS)
1430 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001431 }
1432
1433 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001434 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",
1435 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
1438 }
1439
1440 cur_arg = 2;
1441 while (*args[cur_arg]) {
1442 unsigned int low, high;
1443
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001444 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001445 char *dash = strchr(args[cur_arg], '-');
1446
1447 low = high = str2uic(args[cur_arg]);
1448 if (dash)
1449 high = str2uic(dash + 1);
1450
1451 if (high < low) {
1452 unsigned int swap = low;
1453 low = high;
1454 high = swap;
1455 }
1456
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001457 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001458 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001459 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
1462 }
1463
1464 while (low <= high)
1465 cpus |= 1UL << low++;
1466 }
1467 else {
1468 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1469 file, linenum, args[0], args[cur_arg]);
1470 err_code |= ERR_ALERT | ERR_FATAL;
1471 goto out;
1472 }
1473 cur_arg++;
1474 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001475 for (i = 0; i < LONGBITS; i++)
1476 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001477 global.cpu_map[i] = cpus;
1478#else
1479 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
1482#endif
1483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001485 struct cfg_kw_list *kwl;
1486 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001487 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001488
1489 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1490 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1491 if (kwl->kw[index].section != CFG_GLOBAL)
1492 continue;
1493 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001494 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001495 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001496 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001497 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001498 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001499 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001500 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001501 err_code |= ERR_WARN;
1502 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001503 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001504 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001505 }
1506 }
1507 }
1508
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001510 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001512
Willy Tarreau058e9072009-07-20 09:30:05 +02001513 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001514 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001515 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516}
1517
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001518void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001520 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 defproxy.mode = PR_MODE_TCP;
1522 defproxy.state = PR_STNEW;
1523 defproxy.maxconn = cfg_maxpconn;
1524 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001525
Simon Horman66183002013-02-23 10:16:43 +09001526 defproxy.defsrv.check.inter = DEF_CHKINTR;
1527 defproxy.defsrv.check.fastinter = 0;
1528 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001529 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1530 defproxy.defsrv.agent.fastinter = 0;
1531 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001532 defproxy.defsrv.check.rise = DEF_RISETIME;
1533 defproxy.defsrv.check.fall = DEF_FALLTIME;
1534 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1535 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001536 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001537 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001538 defproxy.defsrv.maxqueue = 0;
1539 defproxy.defsrv.minconn = 0;
1540 defproxy.defsrv.maxconn = 0;
1541 defproxy.defsrv.slowstart = 0;
1542 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1543 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1544 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545}
1546
Willy Tarreauade5ec42010-01-28 19:33:49 +01001547
Willy Tarreau63af98d2014-05-18 08:11:41 +02001548/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1549 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1550 * ERR_FATAL in case of error.
1551 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001552static int create_cond_regex_rule(const char *file, int line,
1553 struct proxy *px, int dir, int action, int flags,
1554 const char *cmd, const char *reg, const char *repl,
1555 const char **cond_start)
1556{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001557 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001558 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001559 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001560 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001561 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001562 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001563 int cs;
1564 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001565
1566 if (px == &defproxy) {
1567 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001568 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001569 goto err;
1570 }
1571
1572 if (*reg == 0) {
1573 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001574 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001575 goto err;
1576 }
1577
1578 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001579 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001580
Willy Tarreau5321c422010-01-28 20:35:13 +01001581 if (cond_start &&
1582 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001583 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1584 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1585 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001586 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001587 goto err;
1588 }
1589 }
1590 else if (cond_start && **cond_start) {
1591 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1592 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001593 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001594 goto err;
1595 }
1596
Willy Tarreau63af98d2014-05-18 08:11:41 +02001597 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001598 (dir == SMP_OPT_DIR_REQ) ?
1599 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1600 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1601 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001602
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001603 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001604 if (!preg) {
1605 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001606 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001607 goto err;
1608 }
1609
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001610 cs = !(flags & REG_ICASE);
1611 cap = !(flags & REG_NOSUB);
1612 error = NULL;
1613 if (!regex_comp(reg, preg, cs, cap, &error)) {
1614 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1615 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001616 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001617 goto err;
1618 }
1619
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001620 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001621 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001622 if (repl && err) {
1623 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1624 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_ALERT | ERR_FATAL;
1626 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001627 }
1628
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001629 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001630 ret_code |= ERR_WARN;
1631
1632 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001633
Willy Tarreau63af98d2014-05-18 08:11:41 +02001634 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001635 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001636 err:
1637 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001638 free(errmsg);
1639 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001640}
1641
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001643 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001644 * Returns the error code, 0 if OK, or any combination of :
1645 * - ERR_ABORT: must abort ASAP
1646 * - ERR_FATAL: we can continue parsing but not start the service
1647 * - ERR_WARN: a warning has been emitted
1648 * - ERR_ALERT: an alert has been emitted
1649 * Only the two first ones can stop processing, the two others are just
1650 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001652int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1653{
1654 static struct peers *curpeers = NULL;
1655 struct peer *newpeer = NULL;
1656 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001657 struct bind_conf *bind_conf;
1658 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001659 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001660 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001661
1662 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001663 if (!*args[1]) {
1664 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001665 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001666 goto out;
1667 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001668
1669 err = invalid_char(args[1]);
1670 if (err) {
1671 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1672 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001673 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001674 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001675 }
1676
1677 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1678 /*
1679 * If there are two proxies with the same name only following
1680 * combinations are allowed:
1681 */
1682 if (strcmp(curpeers->id, args[1]) == 0) {
1683 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1684 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1685 err_code |= ERR_WARN;
1686 }
1687 }
1688
1689 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1690 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1691 err_code |= ERR_ALERT | ERR_ABORT;
1692 goto out;
1693 }
1694
1695 curpeers->next = peers;
1696 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001697 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001698 curpeers->conf.line = linenum;
1699 curpeers->last_change = now.tv_sec;
1700 curpeers->id = strdup(args[1]);
1701 }
1702 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001703 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001704 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001705 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001706
1707 if (!*args[2]) {
1708 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1709 file, linenum, args[0]);
1710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
1712 }
1713
1714 err = invalid_char(args[1]);
1715 if (err) {
1716 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1717 file, linenum, *err, args[1]);
1718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
1720 }
1721
1722 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1723 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1724 err_code |= ERR_ALERT | ERR_ABORT;
1725 goto out;
1726 }
1727
1728 /* the peers are linked backwards first */
1729 curpeers->count++;
1730 newpeer->next = curpeers->remote;
1731 curpeers->remote = newpeer;
1732 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001733 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001734 newpeer->conf.line = linenum;
1735
1736 newpeer->last_change = now.tv_sec;
1737 newpeer->id = strdup(args[1]);
1738
Willy Tarreau902636f2013-03-10 19:44:48 +01001739 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001740 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001741 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001745
1746 proto = protocol_by_family(sk->ss_family);
1747 if (!proto || !proto->connect) {
1748 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1749 file, linenum, args[0], args[1]);
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
1752 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001753
1754 if (port1 != port2) {
1755 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1756 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
1760
Willy Tarreau2aa38802013-02-20 19:20:59 +01001761 if (!port1) {
1762 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1763 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001767
Emeric Brun32da3c42010-09-23 18:39:19 +02001768 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001769 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001770 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001771 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001772
Emeric Brun32da3c42010-09-23 18:39:19 +02001773 if (strcmp(newpeer->id, localpeer) == 0) {
1774 /* Current is local peer, it define a frontend */
1775 newpeer->local = 1;
1776
1777 if (!curpeers->peers_fe) {
1778 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1779 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1780 err_code |= ERR_ALERT | ERR_ABORT;
1781 goto out;
1782 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001783
Willy Tarreau237250c2011-07-29 01:49:03 +02001784 init_new_proxy(curpeers->peers_fe);
1785 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001786
1787 curpeers->peers_fe->last_change = now.tv_sec;
1788 curpeers->peers_fe->id = strdup(args[1]);
1789 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001790 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001791 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1792 curpeers->peers_fe->timeout.connect = 5000;
1793 curpeers->peers_fe->accept = peer_accept;
1794 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001795 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1796 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001797
1798 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1799
Willy Tarreau902636f2013-03-10 19:44:48 +01001800 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1801 if (errmsg && *errmsg) {
1802 indent_msg(&errmsg, 2);
1803 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001804 }
1805 else
1806 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1807 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001808 err_code |= ERR_FATAL;
1809 goto out;
1810 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001811
1812 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001813 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001814 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1815 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1816 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1817 l->accept = session_accept;
1818 l->handler = process_session;
1819 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1820 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1821 global.maxsock += l->maxconn;
1822 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001823 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001824 else {
1825 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1826 file, linenum, args[0], args[1],
1827 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1828 err_code |= ERR_FATAL;
1829 goto out;
1830 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001831 }
1832 } /* neither "peer" nor "peers" */
1833 else if (*args[0] != 0) {
1834 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001840 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001841 return err_code;
1842}
1843
Willy Tarreau3842f002009-06-14 11:39:52 +02001844int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845{
1846 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001847 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001848 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001849 int rc;
1850 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001851 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001852 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001853 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001854 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001855 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 if (!strcmp(args[0], "listen"))
1858 rc = PR_CAP_LISTEN;
1859 else if (!strcmp(args[0], "frontend"))
1860 rc = PR_CAP_FE | PR_CAP_RS;
1861 else if (!strcmp(args[0], "backend"))
1862 rc = PR_CAP_BE | PR_CAP_RS;
1863 else if (!strcmp(args[0], "ruleset"))
1864 rc = PR_CAP_RS;
1865 else
1866 rc = PR_CAP_NONE;
1867
1868 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001869 struct ebpt_node *node;
1870
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 if (!*args[1]) {
1872 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1873 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1874 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_ALERT | ERR_ABORT;
1876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001878
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001879 err = invalid_char(args[1]);
1880 if (err) {
1881 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1882 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001884 }
1885
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001886 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1887 curproxy = container_of(node, struct proxy, conf.by_name);
1888
1889 if (strcmp(curproxy->id, args[1]) != 0)
1890 break;
1891
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001892 /*
1893 * If there are two proxies with the same name only following
1894 * combinations are allowed:
1895 *
1896 * listen backend frontend ruleset
1897 * listen - - - -
1898 * backend - - OK -
1899 * frontend - OK - -
1900 * ruleset - - - -
1901 */
1902
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001903 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1904 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001905 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1906 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1907 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001909 }
1910 }
1911
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1913 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001914 err_code |= ERR_ALERT | ERR_ABORT;
1915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001917
Willy Tarreau97cb7802010-01-03 20:23:58 +01001918 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 curproxy->next = proxy;
1920 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001921 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1922 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001923 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001926 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927
1928 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001930 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001931
Willy Tarreau4348fad2012-09-20 16:48:07 +02001932 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1933
Willy Tarreau902636f2013-03-10 19:44:48 +01001934 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1935 if (errmsg && *errmsg) {
1936 indent_msg(&errmsg, 2);
1937 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001938 }
1939 else
1940 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1941 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_FATAL;
1943 goto out;
1944 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001945
Willy Tarreau4348fad2012-09-20 16:48:07 +02001946 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001947 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
1950
1951 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001952 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001953 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001954
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001957 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001958 curproxy->no_options = defproxy.no_options;
1959 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001960 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001961 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001962 curproxy->except_net = defproxy.except_net;
1963 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001964 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001965 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001967 if (defproxy.fwdfor_hdr_len) {
1968 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1969 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1970 }
1971
Willy Tarreaub86db342009-11-30 11:50:16 +01001972 if (defproxy.orgto_hdr_len) {
1973 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1974 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1975 }
1976
Mark Lamourinec2247f02012-01-04 13:02:01 -05001977 if (defproxy.server_id_hdr_len) {
1978 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1979 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1980 }
1981
Willy Tarreau977b8e42006-12-29 14:19:17 +01001982 if (curproxy->cap & PR_CAP_FE) {
1983 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001984 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001985 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986
1987 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001988 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1989 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001990
1991 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1992 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 if (curproxy->cap & PR_CAP_BE) {
1995 curproxy->fullconn = defproxy.fullconn;
1996 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001997 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001999 if (defproxy.check_req) {
2000 curproxy->check_req = calloc(1, defproxy.check_len);
2001 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002003 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002005 if (defproxy.expect_str) {
2006 curproxy->expect_str = strdup(defproxy.expect_str);
2007 if (defproxy.expect_regex) {
2008 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002009 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2010 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002011 }
2012 }
2013
Willy Tarreau67402132012-05-31 20:40:20 +02002014 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002015 if (defproxy.cookie_name)
2016 curproxy->cookie_name = strdup(defproxy.cookie_name);
2017 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002018 if (defproxy.cookie_domain)
2019 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002020
Willy Tarreau31936852010-10-06 16:59:56 +02002021 if (defproxy.cookie_maxidle)
2022 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2023
2024 if (defproxy.cookie_maxlife)
2025 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2026
Emeric Brun647caf12009-06-30 17:57:00 +02002027 if (defproxy.rdp_cookie_name)
2028 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2029 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2030
Willy Tarreau01732802007-11-01 22:48:15 +01002031 if (defproxy.url_param_name)
2032 curproxy->url_param_name = strdup(defproxy.url_param_name);
2033 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002034
Benoitaffb4812009-03-25 13:02:10 +01002035 if (defproxy.hh_name)
2036 curproxy->hh_name = strdup(defproxy.hh_name);
2037 curproxy->hh_len = defproxy.hh_len;
2038 curproxy->hh_match_domain = defproxy.hh_match_domain;
2039
Willy Tarreauef9a3602012-12-08 22:29:20 +01002040 if (defproxy.conn_src.iface_name)
2041 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2042 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002043 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002044#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002045 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002046#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002049 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002050 if (defproxy.capture_name)
2051 curproxy->capture_name = strdup(defproxy.capture_name);
2052 curproxy->capture_namelen = defproxy.capture_namelen;
2053 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002057 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002058 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002059 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002060 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002061 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 curproxy->mon_net = defproxy.mon_net;
2063 curproxy->mon_mask = defproxy.mon_mask;
2064 if (defproxy.monitor_uri)
2065 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2066 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002067 if (defproxy.defbe.name)
2068 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002069
2070 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002071 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2072 if (curproxy->conf.logformat_string &&
2073 curproxy->conf.logformat_string != default_http_log_format &&
2074 curproxy->conf.logformat_string != default_tcp_log_format &&
2075 curproxy->conf.logformat_string != clf_http_log_format)
2076 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2077
2078 if (defproxy.conf.lfs_file) {
2079 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2080 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2081 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002082 }
2083
2084 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002085 curproxy->timeout.connect = defproxy.timeout.connect;
2086 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002087 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002088 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002089 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002090 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002091 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002092 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002093 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002094 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002095 }
2096
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002098 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002099
2100 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002101 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002102 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002103 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002104 LIST_INIT(&node->list);
2105 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2106 }
2107
Willy Tarreau62a61232013-04-12 18:13:46 +02002108 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2109 if (curproxy->conf.uniqueid_format_string)
2110 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2111
2112 if (defproxy.conf.uif_file) {
2113 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2114 curproxy->conf.uif_line = defproxy.conf.uif_line;
2115 }
William Lallemanda73203e2012-03-12 12:48:57 +01002116
2117 /* copy default header unique id */
2118 if (defproxy.header_unique_id)
2119 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2120
William Lallemand82fe75c2012-10-23 10:25:10 +02002121 /* default compression options */
2122 if (defproxy.comp != NULL) {
2123 curproxy->comp = calloc(1, sizeof(struct comp));
2124 curproxy->comp->algos = defproxy.comp->algos;
2125 curproxy->comp->types = defproxy.comp->types;
2126 }
2127
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002129 curproxy->conf.used_listener_id = EB_ROOT;
2130 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002131
Simon Horman98637e52014-06-20 12:30:16 +09002132 if (defproxy.check_path)
2133 curproxy->check_path = strdup(defproxy.check_path);
2134 if (defproxy.check_command)
2135 curproxy->check_command = strdup(defproxy.check_command);
2136
Willy Tarreau93893792009-07-23 13:19:11 +02002137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 }
2139 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2140 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002141 /* FIXME-20070101: we should do this too at the end of the
2142 * config parsing to free all default values.
2143 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002144 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002145 free(defproxy.check_command);
2146 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002147 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002148 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002149 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002150 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002151 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002152 free(defproxy.capture_name);
2153 free(defproxy.monitor_uri);
2154 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002155 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002156 free(defproxy.fwdfor_hdr_name);
2157 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002158 free(defproxy.orgto_hdr_name);
2159 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002160 free(defproxy.server_id_hdr_name);
2161 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002162 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002163 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002164 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002165 free(defproxy.expect_regex);
2166 defproxy.expect_regex = NULL;
2167 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002168
Willy Tarreau62a61232013-04-12 18:13:46 +02002169 if (defproxy.conf.logformat_string != default_http_log_format &&
2170 defproxy.conf.logformat_string != default_tcp_log_format &&
2171 defproxy.conf.logformat_string != clf_http_log_format)
2172 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002173
Willy Tarreau62a61232013-04-12 18:13:46 +02002174 free(defproxy.conf.uniqueid_format_string);
2175 free(defproxy.conf.lfs_file);
2176 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002177
Willy Tarreaua534fea2008-08-03 12:19:50 +02002178 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002179 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 /* we cannot free uri_auth because it might already be used */
2182 init_default_instance();
2183 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002184 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2185 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002186 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 }
2189 else if (curproxy == NULL) {
2190 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002194
2195 /* update the current file and line being parsed */
2196 curproxy->conf.args.file = curproxy->conf.file;
2197 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002198
2199 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002200 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2201 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2202 if (err_code & ERR_FATAL)
2203 goto out;
2204 }
2205 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002206 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002207 int cur_arg;
2208
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 if (curproxy == &defproxy) {
2210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216
Willy Tarreau24709282013-03-10 21:32:12 +01002217 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002218 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002223
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002224 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002225
2226 /* use default settings for unix sockets */
2227 bind_conf->ux.uid = global.unix_bind.ux.uid;
2228 bind_conf->ux.gid = global.unix_bind.ux.gid;
2229 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002230
2231 /* NOTE: the following line might create several listeners if there
2232 * are comma-separated IPs or port ranges. So all further processing
2233 * will have to be applied to all listeners created after last_listen.
2234 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002235 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2236 if (errmsg && *errmsg) {
2237 indent_msg(&errmsg, 2);
2238 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002239 }
2240 else
2241 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2242 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002246
Willy Tarreau4348fad2012-09-20 16:48:07 +02002247 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2248 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002249 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002250 }
2251
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002252 cur_arg = 2;
2253 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002254 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002255 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002256 char *err;
2257
Willy Tarreau26982662012-09-12 23:17:10 +02002258 kw = bind_find_kw(args[cur_arg]);
2259 if (kw) {
2260 char *err = NULL;
2261 int code;
2262
2263 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002264 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2265 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002266 cur_arg += 1 + kw->skip ;
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270
Willy Tarreau4348fad2012-09-20 16:48:07 +02002271 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002272 err_code |= code;
2273
2274 if (code) {
2275 if (err && *err) {
2276 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002277 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002278 }
2279 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002280 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2281 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002282 if (code & ERR_FATAL) {
2283 free(err);
2284 cur_arg += 1 + kw->skip;
2285 goto out;
2286 }
2287 }
2288 free(err);
2289 cur_arg += 1 + kw->skip;
2290 continue;
2291 }
2292
Willy Tarreau8638f482012-09-18 18:01:17 +02002293 err = NULL;
2294 if (!bind_dumped) {
2295 bind_dump_kws(&err);
2296 indent_msg(&err, 4);
2297 bind_dumped = 1;
2298 }
2299
2300 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2301 file, linenum, args[0], args[1], args[cur_arg],
2302 err ? " Registered keywords :" : "", err ? err : "");
2303 free(err);
2304
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002307 }
Willy Tarreau93893792009-07-23 13:19:11 +02002308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 }
2310 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002311 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2313 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 /* flush useless bits */
2321 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002324 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327
Willy Tarreau1c47f852006-07-09 08:22:27 +02002328 if (!*args[1]) {
2329 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002333 }
2334
Willy Tarreaua534fea2008-08-03 12:19:50 +02002335 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002336 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002337 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002338 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002339 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2340
Willy Tarreau93893792009-07-23 13:19:11 +02002341 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2344 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2345 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2346 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2347 else {
2348 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
2352 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002353 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002354 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002355
2356 if (curproxy == &defproxy) {
2357 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2358 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002361 }
2362
2363 if (!*args[1]) {
2364 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002368 }
2369
2370 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002371 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002372
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002373 if (curproxy->uuid <= 0) {
2374 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002375 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002378 }
2379
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002380 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2381 if (node) {
2382 struct proxy *target = container_of(node, struct proxy, conf.id);
2383 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2384 file, linenum, proxy_type_str(curproxy), curproxy->id,
2385 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002390 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002391 else if (!strcmp(args[0], "description")) {
2392 int i, len=0;
2393 char *d;
2394
Cyril Bonté99ed3272010-01-24 23:29:44 +01002395 if (curproxy == &defproxy) {
2396 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2397 file, linenum, args[0]);
2398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
2400 }
2401
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002402 if (!*args[1]) {
2403 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2404 file, linenum, args[0]);
2405 return -1;
2406 }
2407
Willy Tarreau348acfe2014-04-14 15:00:39 +02002408 for (i = 1; *args[i]; i++)
2409 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002410
2411 d = (char *)calloc(1, len);
2412 curproxy->desc = d;
2413
Willy Tarreau348acfe2014-04-14 15:00:39 +02002414 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2415 for (i = 2; *args[i]; i++)
2416 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002417
2418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2420 curproxy->state = PR_STSTOPPED;
2421 }
2422 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2423 curproxy->state = PR_STNEW;
2424 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002425 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2426 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002427 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002428
2429 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002430 unsigned int low, high;
2431
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002432 if (strcmp(args[cur_arg], "all") == 0) {
2433 set = 0;
2434 break;
2435 }
2436 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002437 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002438 }
2439 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002440 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002441 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002442 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002443 char *dash = strchr(args[cur_arg], '-');
2444
2445 low = high = str2uic(args[cur_arg]);
2446 if (dash)
2447 high = str2uic(dash + 1);
2448
2449 if (high < low) {
2450 unsigned int swap = low;
2451 low = high;
2452 high = swap;
2453 }
2454
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002455 if (low < 1 || high > LONGBITS) {
2456 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2457 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002460 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002461 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002462 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002463 }
2464 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002465 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2466 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002469 }
2470 cur_arg++;
2471 }
2472 curproxy->bind_proc = set;
2473 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002474 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002475 if (curproxy == &defproxy) {
2476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002479 }
2480
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002481 err = invalid_char(args[1]);
2482 if (err) {
2483 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2484 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002486 }
2487
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002488 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002489 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2490 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002493 }
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2496 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497
Willy Tarreau977b8e42006-12-29 14:19:17 +01002498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 if (*(args[1]) == 0) {
2502 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002507
Willy Tarreau67402132012-05-31 20:40:20 +02002508 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002509 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002510 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002511 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 curproxy->cookie_name = strdup(args[1]);
2513 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002514
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 cur_arg = 2;
2516 while (*(args[cur_arg])) {
2517 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002518 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 }
2520 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002521 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002524 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 }
2526 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002527 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 }
2529 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002530 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002532 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002533 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002536 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002538 else if (!strcmp(args[cur_arg], "httponly")) {
2539 curproxy->ck_opts |= PR_CK_HTTPONLY;
2540 }
2541 else if (!strcmp(args[cur_arg], "secure")) {
2542 curproxy->ck_opts |= PR_CK_SECURE;
2543 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002544 else if (!strcmp(args[cur_arg], "domain")) {
2545 if (!*args[cur_arg + 1]) {
2546 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2547 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002550 }
2551
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002552 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002553 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002554 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2555 " dots nor does not start with a dot."
2556 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002557 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002558 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002559 }
2560
2561 err = invalid_domainchar(args[cur_arg + 1]);
2562 if (err) {
2563 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2564 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002567 }
2568
Willy Tarreau68a897b2009-12-03 23:28:34 +01002569 if (!curproxy->cookie_domain) {
2570 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2571 } else {
2572 /* one domain was already specified, add another one by
2573 * building the string which will be returned along with
2574 * the cookie.
2575 */
2576 char *new_ptr;
2577 int new_len = strlen(curproxy->cookie_domain) +
2578 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2579 new_ptr = malloc(new_len);
2580 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2581 free(curproxy->cookie_domain);
2582 curproxy->cookie_domain = new_ptr;
2583 }
Willy Tarreau31936852010-10-06 16:59:56 +02002584 cur_arg++;
2585 }
2586 else if (!strcmp(args[cur_arg], "maxidle")) {
2587 unsigned int maxidle;
2588 const char *res;
2589
2590 if (!*args[cur_arg + 1]) {
2591 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2592 file, linenum, args[cur_arg]);
2593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
2595 }
2596
2597 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2598 if (res) {
2599 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2600 file, linenum, *res, args[cur_arg]);
2601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
2603 }
2604 curproxy->cookie_maxidle = maxidle;
2605 cur_arg++;
2606 }
2607 else if (!strcmp(args[cur_arg], "maxlife")) {
2608 unsigned int maxlife;
2609 const char *res;
2610
2611 if (!*args[cur_arg + 1]) {
2612 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2613 file, linenum, args[cur_arg]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
2618 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2619 if (res) {
2620 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2621 file, linenum, *res, args[cur_arg]);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002626 cur_arg++;
2627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002629 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 +02002630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
2634 cur_arg++;
2635 }
Willy Tarreau67402132012-05-31 20:40:20 +02002636 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2638 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 }
2641
Willy Tarreau67402132012-05-31 20:40:20 +02002642 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2644 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002647
Willy Tarreau67402132012-05-31 20:40:20 +02002648 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002649 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2650 file, linenum);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002654 else if (!strcmp(args[0], "external-check")) {
2655 if (*(args[1]) == 0) {
2656 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2657 file, linenum, args[0]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661
2662 if (!strcmp(args[1], "command")) {
2663 if (*(args[1]) == 0) {
2664 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2665 file, linenum, args[1]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669 free(curproxy->check_command);
2670 curproxy->check_command = strdup(args[2]);
2671 }
2672 else if (!strcmp(args[1], "path")) {
2673 if (*(args[1]) == 0) {
2674 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2675 file, linenum, args[1]);
2676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
2678 }
2679 free(curproxy->check_path);
2680 curproxy->check_path = strdup(args[2]);
2681 }
2682 else {
2683 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2684 file, linenum, args[1]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002689 else if (!strcmp(args[0], "persist")) { /* persist */
2690 if (*(args[1]) == 0) {
2691 Alert("parsing [%s:%d] : missing persist method.\n",
2692 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002695 }
2696
2697 if (!strncmp(args[1], "rdp-cookie", 10)) {
2698 curproxy->options2 |= PR_O2_RDPC_PRST;
2699
Emeric Brunb982a3d2010-01-04 15:45:53 +01002700 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002701 const char *beg, *end;
2702
2703 beg = args[1] + 11;
2704 end = strchr(beg, ')');
2705
2706 if (!end || end == beg) {
2707 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2708 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002711 }
2712
2713 free(curproxy->rdp_cookie_name);
2714 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2715 curproxy->rdp_cookie_len = end-beg;
2716 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002717 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002718 free(curproxy->rdp_cookie_name);
2719 curproxy->rdp_cookie_name = strdup("msts");
2720 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2721 }
2722 else { /* syntax */
2723 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2724 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002727 }
2728 }
2729 else {
2730 Alert("parsing [%s:%d] : unknown persist method.\n",
2731 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002734 }
2735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002737 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002747
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002749 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 }
2754 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->appsession_name = strdup(args[1]);
2757 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2758 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002759 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2760 if (err) {
2761 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2762 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002765 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002766 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002767
Willy Tarreau51041c72007-09-09 21:56:53 +02002768 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2769 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_ABORT;
2771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002773
2774 cur_arg = 6;
2775 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002776 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2777 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002778 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002779 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002780 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002781 } else if (!strcmp(args[cur_arg], "prefix")) {
2782 curproxy->options2 |= PR_O2_AS_PFX;
2783 } else if (!strcmp(args[cur_arg], "mode")) {
2784 if (!*args[cur_arg + 1]) {
2785 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2786 file, linenum, args[0], args[cur_arg]);
2787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
2789 }
2790
2791 cur_arg++;
2792 if (!strcmp(args[cur_arg], "query-string")) {
2793 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2794 curproxy->options2 |= PR_O2_AS_M_QS;
2795 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2796 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2797 curproxy->options2 |= PR_O2_AS_M_PP;
2798 } else {
2799 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
2802 }
2803 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002804 cur_arg++;
2805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002806 } /* Url App Session */
2807 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002810
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002812 if (curproxy == &defproxy) {
2813 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
2816 }
2817
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 if (*(args[4]) == 0) {
2819 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002824 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 curproxy->capture_name = strdup(args[2]);
2826 curproxy->capture_namelen = strlen(curproxy->capture_name);
2827 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 curproxy->to_log |= LW_COOKIE;
2829 }
2830 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2831 struct cap_hdr *hdr;
2832
2833 if (curproxy == &defproxy) {
2834 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 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
2838
2839 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2840 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2841 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
2845
2846 hdr = calloc(sizeof(struct cap_hdr), 1);
2847 hdr->next = curproxy->req_cap;
2848 hdr->name = strdup(args[3]);
2849 hdr->namelen = strlen(args[3]);
2850 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002851 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 hdr->index = curproxy->nb_req_cap++;
2853 curproxy->req_cap = hdr;
2854 curproxy->to_log |= LW_REQHDR;
2855 }
2856 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2857 struct cap_hdr *hdr;
2858
2859 if (curproxy == &defproxy) {
2860 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 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864
2865 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2866 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2867 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
2871 hdr = calloc(sizeof(struct cap_hdr), 1);
2872 hdr->next = curproxy->rsp_cap;
2873 hdr->name = strdup(args[3]);
2874 hdr->namelen = strlen(args[3]);
2875 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002876 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 hdr->index = curproxy->nb_rsp_cap++;
2878 curproxy->rsp_cap = hdr;
2879 curproxy->to_log |= LW_RSPHDR;
2880 }
2881 else {
2882 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 }
2887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 if (*(args[1]) == 0) {
2893 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }
2898 curproxy->conn_retries = atol(args[1]);
2899 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002900 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002901 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002902
2903 if (curproxy == &defproxy) {
2904 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Willy Tarreau20b0de52012-12-24 15:45:22 +01002909 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2910 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2911 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2912 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002913 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002914 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2915 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 +01002916 file, linenum, args[0]);
2917 err_code |= ERR_WARN;
2918 }
2919
Willy Tarreauff011f22011-01-06 17:51:27 +01002920 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002921
Willy Tarreauff011f22011-01-06 17:51:27 +01002922 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002923 err_code |= ERR_ALERT | ERR_ABORT;
2924 goto out;
2925 }
2926
Willy Tarreau5002f572014-04-23 01:32:02 +02002927 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002928 err_code |= warnif_cond_conflicts(rule->cond,
2929 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2930 file, linenum);
2931
Willy Tarreauff011f22011-01-06 17:51:27 +01002932 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002933 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002934 else if (!strcmp(args[0], "http-response")) { /* response access control */
2935 struct http_res_rule *rule;
2936
2937 if (curproxy == &defproxy) {
2938 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
2942
2943 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2944 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2945 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2946 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2947 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2948 file, linenum, args[0]);
2949 err_code |= ERR_WARN;
2950 }
2951
2952 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2953
2954 if (!rule) {
2955 err_code |= ERR_ALERT | ERR_ABORT;
2956 goto out;
2957 }
2958
2959 err_code |= warnif_cond_conflicts(rule->cond,
2960 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2961 file, linenum);
2962
2963 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2964 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002965 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2966 /* set the header name and length into the proxy structure */
2967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2968 err_code |= ERR_WARN;
2969
2970 if (!*args[1]) {
2971 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2972 file, linenum, args[0]);
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
2976
2977 /* set the desired header name */
2978 free(curproxy->server_id_hdr_name);
2979 curproxy->server_id_hdr_name = strdup(args[1]);
2980 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2981 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002982 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002983 struct http_req_rule *rule;
2984
Willy Tarreaub099aca2008-10-12 17:26:37 +02002985 if (curproxy == &defproxy) {
2986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002989 }
2990
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002991 /* emulate "block" using "http-request block". Since these rules are supposed to
2992 * be processed before all http-request rules, we put them into their own list
2993 * and will insert them at the end.
2994 */
2995 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2996 if (!rule) {
2997 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002998 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002999 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003000 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3001 err_code |= warnif_cond_conflicts(rule->cond,
3002 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3003 file, linenum);
3004 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003005
3006 if (!already_warned(WARN_BLOCK_DEPRECATED))
3007 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]);
3008
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003009 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003010 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003011 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003012
Cyril Bonté99ed3272010-01-24 23:29:44 +01003013 if (curproxy == &defproxy) {
3014 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003019 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003020 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3021 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003024 }
3025
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003026 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003027 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003028 err_code |= warnif_cond_conflicts(rule->cond,
3029 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3030 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003031 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003032 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003033 struct switching_rule *rule;
3034
Willy Tarreaub099aca2008-10-12 17:26:37 +02003035 if (curproxy == &defproxy) {
3036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003039 }
3040
Willy Tarreau55ea7572007-06-17 19:56:27 +02003041 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003043
3044 if (*(args[1]) == 0) {
3045 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003048 }
3049
Willy Tarreauf51658d2014-04-23 01:21:56 +02003050 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3051 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3052 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3053 file, linenum, errmsg);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003057
Willy Tarreauf51658d2014-04-23 01:21:56 +02003058 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003059 }
3060
3061 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3062 rule->cond = cond;
3063 rule->be.name = strdup(args[1]);
3064 LIST_INIT(&rule->list);
3065 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3066 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003067 else if (strcmp(args[0], "use-server") == 0) {
3068 struct server_rule *rule;
3069
3070 if (curproxy == &defproxy) {
3071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
3076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3077 err_code |= ERR_WARN;
3078
3079 if (*(args[1]) == 0) {
3080 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
3085 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3086 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3087 file, linenum, args[0]);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
3091
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003092 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3093 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3094 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003099 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003100
3101 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3102 rule->cond = cond;
3103 rule->srv.name = strdup(args[1]);
3104 LIST_INIT(&rule->list);
3105 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3106 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3107 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003108 else if ((!strcmp(args[0], "force-persist")) ||
3109 (!strcmp(args[0], "ignore-persist"))) {
3110 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003111
3112 if (curproxy == &defproxy) {
3113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
3118 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3119 err_code |= ERR_WARN;
3120
Willy Tarreauef6494c2010-01-28 17:12:36 +01003121 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003122 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3123 file, linenum, args[0]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003128 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3129 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3130 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003135 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3136 * where force-persist is applied.
3137 */
3138 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003139
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003140 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003141 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003142 if (!strcmp(args[0], "force-persist")) {
3143 rule->type = PERSIST_TYPE_FORCE;
3144 } else {
3145 rule->type = PERSIST_TYPE_IGNORE;
3146 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003147 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003148 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003149 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 else if (!strcmp(args[0], "stick-table")) {
3151 int myidx = 1;
3152
Emeric Brun32da3c42010-09-23 18:39:19 +02003153 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 curproxy->table.type = (unsigned int)-1;
3155 while (*args[myidx]) {
3156 const char *err;
3157
3158 if (strcmp(args[myidx], "size") == 0) {
3159 myidx++;
3160 if (!*(args[myidx])) {
3161 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3162 file, linenum, args[myidx-1]);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165 }
3166 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3167 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3168 file, linenum, *err, args[myidx-1]);
3169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
3171 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003172 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003173 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003174 else if (strcmp(args[myidx], "peers") == 0) {
3175 myidx++;
Godbach50523162013-12-11 19:48:57 +08003176 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003177 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3178 file, linenum, args[myidx-1]);
3179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Godbach50523162013-12-11 19:48:57 +08003181 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003182 curproxy->table.peers.name = strdup(args[myidx++]);
3183 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003184 else if (strcmp(args[myidx], "expire") == 0) {
3185 myidx++;
3186 if (!*(args[myidx])) {
3187 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3188 file, linenum, args[myidx-1]);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
3191 }
3192 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3193 if (err) {
3194 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3195 file, linenum, *err, args[myidx-1]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003200 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 }
3202 else if (strcmp(args[myidx], "nopurge") == 0) {
3203 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003204 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003205 }
3206 else if (strcmp(args[myidx], "type") == 0) {
3207 myidx++;
3208 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3209 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3210 file, linenum, args[myidx]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003214 /* myidx already points to next arg */
3215 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003216 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003217 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003218 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003219
3220 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003221 nw = args[myidx];
3222 while (*nw) {
3223 /* the "store" keyword supports a comma-separated list */
3224 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003225 sa = NULL; /* store arg */
3226 while (*nw && *nw != ',') {
3227 if (*nw == '(') {
3228 *nw = 0;
3229 sa = ++nw;
3230 while (*nw != ')') {
3231 if (!*nw) {
3232 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3233 file, linenum, args[0], cw);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237 nw++;
3238 }
3239 *nw = '\0';
3240 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003241 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003242 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003243 if (*nw)
3244 *nw++ = '\0';
3245 type = stktable_get_data_type(cw);
3246 if (type < 0) {
3247 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3248 file, linenum, args[0], cw);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
Willy Tarreauac782882010-06-20 10:41:54 +02003252
3253 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3254 switch (err) {
3255 case PE_NONE: break;
3256 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003257 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3258 file, linenum, args[0], cw);
3259 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003260 break;
3261
3262 case PE_ARG_MISSING:
3263 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3264 file, linenum, args[0], cw);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267
3268 case PE_ARG_NOT_USED:
3269 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3270 file, linenum, args[0], cw);
3271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
3273
3274 default:
3275 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3276 file, linenum, args[0], cw);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003279 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003280 }
3281 myidx++;
3282 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003283 else {
3284 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3285 file, linenum, args[myidx]);
3286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003288 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003289 }
3290
3291 if (!curproxy->table.size) {
3292 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3293 file, linenum);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
3298 if (curproxy->table.type == (unsigned int)-1) {
3299 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3300 file, linenum);
3301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
3303 }
3304 }
3305 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003306 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003307 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003308 int myidx = 0;
3309 const char *name = NULL;
3310 int flags;
3311
3312 if (curproxy == &defproxy) {
3313 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316 }
3317
3318 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3319 err_code |= ERR_WARN;
3320 goto out;
3321 }
3322
3323 myidx++;
3324 if ((strcmp(args[myidx], "store") == 0) ||
3325 (strcmp(args[myidx], "store-request") == 0)) {
3326 myidx++;
3327 flags = STK_IS_STORE;
3328 }
3329 else if (strcmp(args[myidx], "store-response") == 0) {
3330 myidx++;
3331 flags = STK_IS_STORE | STK_ON_RSP;
3332 }
3333 else if (strcmp(args[myidx], "match") == 0) {
3334 myidx++;
3335 flags = STK_IS_MATCH;
3336 }
3337 else if (strcmp(args[myidx], "on") == 0) {
3338 myidx++;
3339 flags = STK_IS_MATCH | STK_IS_STORE;
3340 }
3341 else {
3342 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346
3347 if (*(args[myidx]) == 0) {
3348 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
3351 }
3352
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003353 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003354 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003355 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003356 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003362 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3363 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3364 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003365 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003366 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 goto out;
3368 }
3369 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003370 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3371 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3372 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003373 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003374 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003375 goto out;
3376 }
3377 }
3378
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003379 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003380 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003381
Emeric Brunb982a3d2010-01-04 15:45:53 +01003382 if (strcmp(args[myidx], "table") == 0) {
3383 myidx++;
3384 name = args[myidx++];
3385 }
3386
Willy Tarreauef6494c2010-01-28 17:12:36 +01003387 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003388 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3389 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3390 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003391 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003392 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 goto out;
3394 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003395 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003396 else if (*(args[myidx])) {
3397 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3398 file, linenum, args[0], args[myidx]);
3399 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003400 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003401 goto out;
3402 }
Emeric Brun97679e72010-09-23 17:56:44 +02003403 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003404 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003405 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003406 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003407
Emeric Brunb982a3d2010-01-04 15:45:53 +01003408 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3409 rule->cond = cond;
3410 rule->expr = expr;
3411 rule->flags = flags;
3412 rule->table.name = name ? strdup(name) : NULL;
3413 LIST_INIT(&rule->list);
3414 if (flags & STK_ON_RSP)
3415 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3416 else
3417 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 else if (!strcmp(args[0], "stats")) {
3420 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3421 curproxy->uri_auth = NULL; /* we must detach from the default config */
3422
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003423 if (!*args[1]) {
3424 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003425 } else if (!strcmp(args[1], "admin")) {
3426 struct stats_admin_rule *rule;
3427
3428 if (curproxy == &defproxy) {
3429 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433
3434 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3435 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3436 err_code |= ERR_ALERT | ERR_ABORT;
3437 goto out;
3438 }
3439
3440 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3441 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3442 file, linenum, args[0], args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003446 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3447 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3448 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003453 err_code |= warnif_cond_conflicts(cond,
3454 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3455 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003456
3457 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3458 rule->cond = cond;
3459 LIST_INIT(&rule->list);
3460 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 } else if (!strcmp(args[1], "uri")) {
3462 if (*(args[2]) == 0) {
3463 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
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 Tarreaubaaee002006-06-26 02:48:02 +02003470 }
3471 } else if (!strcmp(args[1], "realm")) {
3472 if (*(args[2]) == 0) {
3473 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_ABORT;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003481 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003482 unsigned interval;
3483
3484 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3485 if (err) {
3486 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3487 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003490 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3491 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_ABORT;
3493 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003494 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003495 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003496 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003497
3498 if (curproxy == &defproxy) {
3499 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503
3504 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3505 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3506 err_code |= ERR_ALERT | ERR_ABORT;
3507 goto out;
3508 }
3509
Willy Tarreauff011f22011-01-06 17:51:27 +01003510 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3511 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003512 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3513 file, linenum, args[0]);
3514 err_code |= ERR_WARN;
3515 }
3516
Willy Tarreauff011f22011-01-06 17:51:27 +01003517 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003518
Willy Tarreauff011f22011-01-06 17:51:27 +01003519 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003520 err_code |= ERR_ALERT | ERR_ABORT;
3521 goto out;
3522 }
3523
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003524 err_code |= warnif_cond_conflicts(rule->cond,
3525 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3526 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003527 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003528
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 } else if (!strcmp(args[1], "auth")) {
3530 if (*(args[2]) == 0) {
3531 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3535 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_ABORT;
3537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
3539 } else if (!strcmp(args[1], "scope")) {
3540 if (*(args[2]) == 0) {
3541 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_ABORT;
3547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 }
3549 } else if (!strcmp(args[1], "enable")) {
3550 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3551 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_ABORT;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003555 } else if (!strcmp(args[1], "hide-version")) {
3556 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3557 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_ABORT;
3559 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003560 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003561 } else if (!strcmp(args[1], "show-legends")) {
3562 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3563 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3564 err_code |= ERR_ALERT | ERR_ABORT;
3565 goto out;
3566 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003567 } else if (!strcmp(args[1], "show-node")) {
3568
3569 if (*args[2]) {
3570 int i;
3571 char c;
3572
3573 for (i=0; args[2][i]; i++) {
3574 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003575 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3576 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003577 break;
3578 }
3579
3580 if (!i || args[2][i]) {
3581 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3582 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3583 file, linenum, args[0], args[1]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
3587 }
3588
3589 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3590 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3591 err_code |= ERR_ALERT | ERR_ABORT;
3592 goto out;
3593 }
3594 } else if (!strcmp(args[1], "show-desc")) {
3595 char *desc = NULL;
3596
3597 if (*args[2]) {
3598 int i, len=0;
3599 char *d;
3600
Willy Tarreau348acfe2014-04-14 15:00:39 +02003601 for (i = 2; *args[i]; i++)
3602 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003603
3604 desc = d = (char *)calloc(1, len);
3605
Willy Tarreau348acfe2014-04-14 15:00:39 +02003606 d += snprintf(d, desc + len - d, "%s", args[2]);
3607 for (i = 3; *args[i]; i++)
3608 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003609 }
3610
3611 if (!*args[2] && !global.desc)
3612 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3613 file, linenum, args[1]);
3614 else {
3615 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3616 free(desc);
3617 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3618 err_code |= ERR_ALERT | ERR_ABORT;
3619 goto out;
3620 }
3621 free(desc);
3622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003624stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003625 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 +01003626 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
3630 }
3631 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003632 int optnum;
3633
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003634 if (*(args[1]) == '\0') {
3635 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003640
3641 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3642 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003643 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3644 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3645 file, linenum, cfg_opts[optnum].name);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
Willy Tarreau93893792009-07-23 13:19:11 +02003649 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3650 err_code |= ERR_WARN;
3651 goto out;
3652 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003653
Willy Tarreau3842f002009-06-14 11:39:52 +02003654 curproxy->no_options &= ~cfg_opts[optnum].val;
3655 curproxy->options &= ~cfg_opts[optnum].val;
3656
3657 switch (kwm) {
3658 case KWM_STD:
3659 curproxy->options |= cfg_opts[optnum].val;
3660 break;
3661 case KWM_NO:
3662 curproxy->no_options |= cfg_opts[optnum].val;
3663 break;
3664 case KWM_DEF: /* already cleared */
3665 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003666 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003667
Willy Tarreau93893792009-07-23 13:19:11 +02003668 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003669 }
3670 }
3671
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003672 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3673 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003674 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3675 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3676 file, linenum, cfg_opts2[optnum].name);
3677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
Willy Tarreau93893792009-07-23 13:19:11 +02003680 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3681 err_code |= ERR_WARN;
3682 goto out;
3683 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003684
Willy Tarreau3842f002009-06-14 11:39:52 +02003685 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3686 curproxy->options2 &= ~cfg_opts2[optnum].val;
3687
3688 switch (kwm) {
3689 case KWM_STD:
3690 curproxy->options2 |= cfg_opts2[optnum].val;
3691 break;
3692 case KWM_NO:
3693 curproxy->no_options2 |= cfg_opts2[optnum].val;
3694 break;
3695 case KWM_DEF: /* already cleared */
3696 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003697 }
Willy Tarreau93893792009-07-23 13:19:11 +02003698 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003699 }
3700 }
3701
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003702 /* HTTP options override each other. They can be cancelled using
3703 * "no option xxx" which only switches to default mode if the mode
3704 * was this one (useful for cancelling options set in defaults
3705 * sections).
3706 */
3707 if (strcmp(args[1], "httpclose") == 0) {
3708 if (kwm == KWM_STD) {
3709 curproxy->options &= ~PR_O_HTTP_MODE;
3710 curproxy->options |= PR_O_HTTP_PCL;
3711 goto out;
3712 }
3713 else if (kwm == KWM_NO) {
3714 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3715 curproxy->options &= ~PR_O_HTTP_MODE;
3716 goto out;
3717 }
3718 }
3719 else if (strcmp(args[1], "forceclose") == 0) {
3720 if (kwm == KWM_STD) {
3721 curproxy->options &= ~PR_O_HTTP_MODE;
3722 curproxy->options |= PR_O_HTTP_FCL;
3723 goto out;
3724 }
3725 else if (kwm == KWM_NO) {
3726 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3727 curproxy->options &= ~PR_O_HTTP_MODE;
3728 goto out;
3729 }
3730 }
3731 else if (strcmp(args[1], "http-server-close") == 0) {
3732 if (kwm == KWM_STD) {
3733 curproxy->options &= ~PR_O_HTTP_MODE;
3734 curproxy->options |= PR_O_HTTP_SCL;
3735 goto out;
3736 }
3737 else if (kwm == KWM_NO) {
3738 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3739 curproxy->options &= ~PR_O_HTTP_MODE;
3740 goto out;
3741 }
3742 }
3743 else if (strcmp(args[1], "http-keep-alive") == 0) {
3744 if (kwm == KWM_STD) {
3745 curproxy->options &= ~PR_O_HTTP_MODE;
3746 curproxy->options |= PR_O_HTTP_KAL;
3747 goto out;
3748 }
3749 else if (kwm == KWM_NO) {
3750 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3751 curproxy->options &= ~PR_O_HTTP_MODE;
3752 goto out;
3753 }
3754 }
3755 else if (strcmp(args[1], "http-tunnel") == 0) {
3756 if (kwm == KWM_STD) {
3757 curproxy->options &= ~PR_O_HTTP_MODE;
3758 curproxy->options |= PR_O_HTTP_TUN;
3759 goto out;
3760 }
3761 else if (kwm == KWM_NO) {
3762 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3763 curproxy->options &= ~PR_O_HTTP_MODE;
3764 goto out;
3765 }
3766 }
3767
Willy Tarreau3842f002009-06-14 11:39:52 +02003768 if (kwm != KWM_STD) {
3769 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003770 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003773 }
3774
Emeric Brun3a058f32009-06-30 18:26:00 +02003775 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003776 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003778 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003779 if (*(args[2]) != '\0') {
3780 if (!strcmp(args[2], "clf")) {
3781 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003782 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003783 } else {
3784 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003787 }
3788 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003789 if (curproxy->conf.logformat_string != default_http_log_format &&
3790 curproxy->conf.logformat_string != default_tcp_log_format &&
3791 curproxy->conf.logformat_string != clf_http_log_format)
3792 free(curproxy->conf.logformat_string);
3793 curproxy->conf.logformat_string = logformat;
3794
3795 free(curproxy->conf.lfs_file);
3796 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3797 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003798 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003799 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003801 if (curproxy->conf.logformat_string != default_http_log_format &&
3802 curproxy->conf.logformat_string != default_tcp_log_format &&
3803 curproxy->conf.logformat_string != clf_http_log_format)
3804 free(curproxy->conf.logformat_string);
3805 curproxy->conf.logformat_string = default_tcp_log_format;
3806
3807 free(curproxy->conf.lfs_file);
3808 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3809 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 else if (!strcmp(args[1], "tcpka")) {
3812 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003813 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003815
3816 if (curproxy->cap & PR_CAP_FE)
3817 curproxy->options |= PR_O_TCP_CLI_KA;
3818 if (curproxy->cap & PR_CAP_BE)
3819 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
3821 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003822 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_WARN;
3824
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003826 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003827 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003828 curproxy->options2 &= ~PR_O2_CHK_ANY;
3829 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 if (!*args[2]) { /* no argument */
3831 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3832 curproxy->check_len = strlen(DEF_CHECK_REQ);
3833 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003834 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 curproxy->check_req = (char *)malloc(reqlen);
3836 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003837 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003839 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 if (*args[4])
3841 reqlen += strlen(args[4]);
3842 else
3843 reqlen += strlen("HTTP/1.0");
3844
3845 curproxy->check_req = (char *)malloc(reqlen);
3846 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003847 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003849 }
3850 else if (!strcmp(args[1], "ssl-hello-chk")) {
3851 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003854
Willy Tarreaua534fea2008-08-03 12:19:50 +02003855 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003856 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003857 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003858 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreau23677902007-05-08 23:50:35 +02003860 else if (!strcmp(args[1], "smtpchk")) {
3861 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003862 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003863 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003864 curproxy->options2 &= ~PR_O2_CHK_ANY;
3865 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003866
3867 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3868 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3869 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3870 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3871 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3872 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3873 curproxy->check_req = (char *)malloc(reqlen);
3874 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3875 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3876 } else {
3877 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3878 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3879 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3880 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3881 }
3882 }
3883 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003884 else if (!strcmp(args[1], "pgsql-check")) {
3885 /* use PostgreSQL request to check servers' health */
3886 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3887 err_code |= ERR_WARN;
3888
3889 free(curproxy->check_req);
3890 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003891 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003892 curproxy->options2 |= PR_O2_PGSQL_CHK;
3893
3894 if (*(args[2])) {
3895 int cur_arg = 2;
3896
3897 while (*(args[cur_arg])) {
3898 if (strcmp(args[cur_arg], "user") == 0) {
3899 char * packet;
3900 uint32_t packet_len;
3901 uint32_t pv;
3902
3903 /* suboption header - needs additional argument for it */
3904 if (*(args[cur_arg+1]) == 0) {
3905 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3906 file, linenum, args[0], args[1], args[cur_arg]);
3907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
3909 }
3910
3911 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3912 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3913 pv = htonl(0x30000); /* protocol version 3.0 */
3914
3915 packet = (char*) calloc(1, packet_len);
3916
3917 memcpy(packet + 4, &pv, 4);
3918
3919 /* copy "user" */
3920 memcpy(packet + 8, "user", 4);
3921
3922 /* copy username */
3923 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3924
3925 free(curproxy->check_req);
3926 curproxy->check_req = packet;
3927 curproxy->check_len = packet_len;
3928
3929 packet_len = htonl(packet_len);
3930 memcpy(packet, &packet_len, 4);
3931 cur_arg += 2;
3932 } else {
3933 /* unknown suboption - catchall */
3934 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3935 file, linenum, args[0], args[1]);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
3938 }
3939 } /* end while loop */
3940 }
3941 }
3942
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003943 else if (!strcmp(args[1], "redis-check")) {
3944 /* use REDIS PING request to check servers' health */
3945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3946 err_code |= ERR_WARN;
3947
3948 free(curproxy->check_req);
3949 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003950 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003951 curproxy->options2 |= PR_O2_REDIS_CHK;
3952
3953 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3954 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3955 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3956 }
3957
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003958 else if (!strcmp(args[1], "mysql-check")) {
3959 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003960 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3961 err_code |= ERR_WARN;
3962
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003963 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003964 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003965 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003966 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003967
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003968 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003969 * const char mysql40_client_auth_pkt[] = {
3970 * "\x0e\x00\x00" // packet length
3971 * "\x01" // packet number
3972 * "\x00\x00" // client capabilities
3973 * "\x00\x00\x01" // max packet
3974 * "haproxy\x00" // username (null terminated string)
3975 * "\x00" // filler (always 0x00)
3976 * "\x01\x00\x00" // packet length
3977 * "\x00" // packet number
3978 * "\x01" // COM_QUIT command
3979 * };
3980 */
3981
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003982 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3983 * const char mysql41_client_auth_pkt[] = {
3984 * "\x0e\x00\x00\" // packet length
3985 * "\x01" // packet number
3986 * "\x00\x00\x00\x00" // client capabilities
3987 * "\x00\x00\x00\x01" // max packet
3988 * "\x21" // character set (UTF-8)
3989 * char[23] // All zeroes
3990 * "haproxy\x00" // username (null terminated string)
3991 * "\x00" // filler (always 0x00)
3992 * "\x01\x00\x00" // packet length
3993 * "\x00" // packet number
3994 * "\x01" // COM_QUIT command
3995 * };
3996 */
3997
3998
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003999 if (*(args[2])) {
4000 int cur_arg = 2;
4001
4002 while (*(args[cur_arg])) {
4003 if (strcmp(args[cur_arg], "user") == 0) {
4004 char *mysqluser;
4005 int packetlen, reqlen, userlen;
4006
4007 /* suboption header - needs additional argument for it */
4008 if (*(args[cur_arg+1]) == 0) {
4009 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4010 file, linenum, args[0], args[1], args[cur_arg]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014 mysqluser = args[cur_arg + 1];
4015 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004016
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004017 if (*(args[cur_arg+2])) {
4018 if (!strcmp(args[cur_arg+2], "post-41")) {
4019 packetlen = userlen + 7 + 27;
4020 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004021
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004022 free(curproxy->check_req);
4023 curproxy->check_req = (char *)calloc(1, reqlen);
4024 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004025
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004026 snprintf(curproxy->check_req, 4, "%c%c%c",
4027 ((unsigned char) packetlen & 0xff),
4028 ((unsigned char) (packetlen >> 8) & 0xff),
4029 ((unsigned char) (packetlen >> 16) & 0xff));
4030
4031 curproxy->check_req[3] = 1;
4032 curproxy->check_req[5] = 130;
4033 curproxy->check_req[11] = 1;
4034 curproxy->check_req[12] = 33;
4035 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4036 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4037 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4038 cur_arg += 3;
4039 } else {
4040 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044 } else {
4045 packetlen = userlen + 7;
4046 reqlen = packetlen + 9;
4047
4048 free(curproxy->check_req);
4049 curproxy->check_req = (char *)calloc(1, reqlen);
4050 curproxy->check_len = reqlen;
4051
4052 snprintf(curproxy->check_req, 4, "%c%c%c",
4053 ((unsigned char) packetlen & 0xff),
4054 ((unsigned char) (packetlen >> 8) & 0xff),
4055 ((unsigned char) (packetlen >> 16) & 0xff));
4056
4057 curproxy->check_req[3] = 1;
4058 curproxy->check_req[5] = 128;
4059 curproxy->check_req[8] = 1;
4060 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4061 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4062 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4063 cur_arg += 2;
4064 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004065 } else {
4066 /* unknown suboption - catchall */
4067 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4068 file, linenum, args[0], args[1]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072 } /* end while loop */
4073 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004074 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004075 else if (!strcmp(args[1], "ldap-check")) {
4076 /* use LDAP request to check servers' health */
4077 free(curproxy->check_req);
4078 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004079 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004080 curproxy->options2 |= PR_O2_LDAP_CHK;
4081
4082 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4083 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4084 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4085 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004086 else if (!strcmp(args[1], "tcp-check")) {
4087 /* use raw TCPCHK send/expect to check servers' health */
4088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4089 err_code |= ERR_WARN;
4090
4091 free(curproxy->check_req);
4092 curproxy->check_req = NULL;
4093 curproxy->options2 &= ~PR_O2_CHK_ANY;
4094 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4095 }
Simon Horman98637e52014-06-20 12:30:16 +09004096 else if (!strcmp(args[1], "external-check")) {
4097 /* excute an external command to check servers' health */
4098 free(curproxy->check_req);
4099 curproxy->check_req = NULL;
4100 curproxy->options2 &= ~PR_O2_CHK_ANY;
4101 curproxy->options2 |= PR_O2_EXT_CHK;
4102 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004103 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004104 int cur_arg;
4105
4106 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4107 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004108 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004109
Willy Tarreau87cf5142011-08-19 22:57:24 +02004110 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004111
4112 free(curproxy->fwdfor_hdr_name);
4113 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4114 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4115
4116 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4117 cur_arg = 2;
4118 while (*(args[cur_arg])) {
4119 if (!strcmp(args[cur_arg], "except")) {
4120 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004121 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004122 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4123 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004126 }
4127 /* flush useless bits */
4128 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004129 cur_arg += 2;
4130 } else if (!strcmp(args[cur_arg], "header")) {
4131 /* suboption header - needs additional argument for it */
4132 if (*(args[cur_arg+1]) == 0) {
4133 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4134 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004137 }
4138 free(curproxy->fwdfor_hdr_name);
4139 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4140 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4141 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004142 } else if (!strcmp(args[cur_arg], "if-none")) {
4143 curproxy->options &= ~PR_O_FF_ALWAYS;
4144 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004145 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004146 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004147 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004148 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004151 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004152 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004153 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004154 else if (!strcmp(args[1], "originalto")) {
4155 int cur_arg;
4156
4157 /* insert x-original-to field, but not for the IP address listed as an except.
4158 * set default options (ie: bitfield, header name, etc)
4159 */
4160
4161 curproxy->options |= PR_O_ORGTO;
4162
4163 free(curproxy->orgto_hdr_name);
4164 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4165 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4166
Willy Tarreau87cf5142011-08-19 22:57:24 +02004167 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004168 cur_arg = 2;
4169 while (*(args[cur_arg])) {
4170 if (!strcmp(args[cur_arg], "except")) {
4171 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004172 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 +02004173 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4174 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004177 }
4178 /* flush useless bits */
4179 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4180 cur_arg += 2;
4181 } else if (!strcmp(args[cur_arg], "header")) {
4182 /* suboption header - needs additional argument for it */
4183 if (*(args[cur_arg+1]) == 0) {
4184 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4185 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004188 }
4189 free(curproxy->orgto_hdr_name);
4190 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4191 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4192 cur_arg += 2;
4193 } else {
4194 /* unknown suboption - catchall */
4195 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4196 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004199 }
4200 } /* end while loop */
4201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 else {
4203 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 }
Willy Tarreau93893792009-07-23 13:19:11 +02004207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004209 else if (!strcmp(args[0], "default_backend")) {
4210 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004212
4213 if (*(args[1]) == 0) {
4214 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004217 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004218 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004219 curproxy->defbe.name = strdup(args[1]);
4220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004224
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004225 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4226 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 +01004227 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 /* enable reconnections to dispatch */
4230 curproxy->options |= PR_O_REDISP;
4231 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004232 else if (!strcmp(args[0], "http-check")) {
4233 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004235
4236 if (strcmp(args[1], "disable-on-404") == 0) {
4237 /* enable a graceful server shutdown on an HTTP 404 response */
4238 curproxy->options |= PR_O_DISABLE404;
4239 }
Willy Tarreauef781042010-01-27 11:53:01 +01004240 else if (strcmp(args[1], "send-state") == 0) {
4241 /* enable emission of the apparent state of a server in HTTP checks */
4242 curproxy->options2 |= PR_O2_CHK_SNDST;
4243 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004244 else if (strcmp(args[1], "expect") == 0) {
4245 const char *ptr_arg;
4246 int cur_arg;
4247
4248 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4249 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253
4254 cur_arg = 2;
4255 /* consider exclamation marks, sole or at the beginning of a word */
4256 while (*(ptr_arg = args[cur_arg])) {
4257 while (*ptr_arg == '!') {
4258 curproxy->options2 ^= PR_O2_EXP_INV;
4259 ptr_arg++;
4260 }
4261 if (*ptr_arg)
4262 break;
4263 cur_arg++;
4264 }
4265 /* now ptr_arg points to the beginning of a word past any possible
4266 * exclamation mark, and cur_arg is the argument which holds this word.
4267 */
4268 if (strcmp(ptr_arg, "status") == 0) {
4269 if (!*(args[cur_arg + 1])) {
4270 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4271 file, linenum, args[0], args[1], ptr_arg);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004276 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004277 curproxy->expect_str = strdup(args[cur_arg + 1]);
4278 }
4279 else if (strcmp(ptr_arg, "string") == 0) {
4280 if (!*(args[cur_arg + 1])) {
4281 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4282 file, linenum, args[0], args[1], ptr_arg);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004287 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004288 curproxy->expect_str = strdup(args[cur_arg + 1]);
4289 }
4290 else if (strcmp(ptr_arg, "rstatus") == 0) {
4291 if (!*(args[cur_arg + 1])) {
4292 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4293 file, linenum, args[0], args[1], ptr_arg);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004298 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004299 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004300 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004301 free(curproxy->expect_regex);
4302 curproxy->expect_regex = NULL;
4303 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004304 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004305 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4306 error = NULL;
4307 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4308 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4309 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4310 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
4314 }
4315 else if (strcmp(ptr_arg, "rstring") == 0) {
4316 if (!*(args[cur_arg + 1])) {
4317 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4318 file, linenum, args[0], args[1], ptr_arg);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004323 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004324 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004325 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004326 free(curproxy->expect_regex);
4327 curproxy->expect_regex = NULL;
4328 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004329 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004330 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4331 error = NULL;
4332 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4333 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4334 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4335 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339 }
4340 else {
4341 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4342 file, linenum, args[0], args[1], ptr_arg);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004347 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004348 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 +02004349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004351 }
4352 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004353 else if (!strcmp(args[0], "tcp-check")) {
4354 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4355 err_code |= ERR_WARN;
4356
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004357 if (strcmp(args[1], "connect") == 0) {
4358 const char *ptr_arg;
4359 int cur_arg;
4360 struct tcpcheck_rule *tcpcheck;
4361 struct list *l;
4362
4363 /* check if first rule is also a 'connect' action */
4364 l = (struct list *)&curproxy->tcpcheck_rules;
4365 if (l->p != l->n) {
4366 tcpcheck = (struct tcpcheck_rule *)l->n;
4367 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4368 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4369 file, linenum);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373 }
4374
4375 cur_arg = 2;
4376 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4377 tcpcheck->action = TCPCHK_ACT_CONNECT;
4378
4379 /* parsing each parameters to fill up the rule */
4380 while (*(ptr_arg = args[cur_arg])) {
4381 /* tcp port */
4382 if (strcmp(args[cur_arg], "port") == 0) {
4383 if ( (atol(args[cur_arg + 1]) > 65535) ||
4384 (atol(args[cur_arg + 1]) < 1) ){
4385 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4386 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
4390 tcpcheck->port = atol(args[cur_arg + 1]);
4391 cur_arg += 2;
4392 }
4393 /* send proxy protocol */
4394 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4395 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4396 cur_arg++;
4397 }
4398#ifdef USE_OPENSSL
4399 else if (strcmp(args[cur_arg], "ssl") == 0) {
4400 curproxy->options |= PR_O_TCPCHK_SSL;
4401 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4402 cur_arg++;
4403 }
4404#endif /* USE_OPENSSL */
4405 else {
4406#ifdef USE_OPENSSL
4407 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4408#else /* USE_OPENSSL */
4409 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4410#endif /* USE_OPENSSL */
4411 file, linenum, args[0], args[1], args[cur_arg]);
4412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
4414 }
4415
4416 }
4417
4418 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4419 }
4420 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004421 if (! *(args[2]) ) {
4422 /* SEND string expected */
4423 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4424 file, linenum, args[0], args[1], args[2]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 } else {
4428 struct tcpcheck_rule *tcpcheck;
4429
4430 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4431
4432 tcpcheck->action = TCPCHK_ACT_SEND;
4433 tcpcheck->string_len = strlen(args[2]);
4434 tcpcheck->string = strdup(args[2]);
4435 tcpcheck->expect_regex = NULL;
4436
4437 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4438 }
4439 }
4440 else if (strcmp(args[1], "send-binary") == 0) {
4441 if (! *(args[2]) ) {
4442 /* SEND binary string expected */
4443 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4444 file, linenum, args[0], args[1], args[2]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 } else {
4448 struct tcpcheck_rule *tcpcheck;
4449 char *err = NULL;
4450
4451 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4452
4453 tcpcheck->action = TCPCHK_ACT_SEND;
4454 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4455 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4456 file, linenum, args[0], args[1], args[2], err);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
4460 tcpcheck->expect_regex = NULL;
4461
4462 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4463 }
4464 }
4465 else if (strcmp(args[1], "expect") == 0) {
4466 const char *ptr_arg;
4467 int cur_arg;
4468 int inverse = 0;
4469
4470 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4471 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
4475
4476 cur_arg = 2;
4477 /* consider exclamation marks, sole or at the beginning of a word */
4478 while (*(ptr_arg = args[cur_arg])) {
4479 while (*ptr_arg == '!') {
4480 inverse = !inverse;
4481 ptr_arg++;
4482 }
4483 if (*ptr_arg)
4484 break;
4485 cur_arg++;
4486 }
4487 /* now ptr_arg points to the beginning of a word past any possible
4488 * exclamation mark, and cur_arg is the argument which holds this word.
4489 */
4490 if (strcmp(ptr_arg, "binary") == 0) {
4491 if (!*(args[cur_arg + 1])) {
4492 Alert("parsing [%s:%d] : '%s %s %s' expects <binary 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 char *err = NULL;
4499
4500 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4501
4502 tcpcheck->action = TCPCHK_ACT_EXPECT;
4503 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4504 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4505 file, linenum, args[0], args[1], args[2], err);
4506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
4508 }
4509 tcpcheck->expect_regex = NULL;
4510 tcpcheck->inverse = inverse;
4511
4512 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4513 }
4514 else if (strcmp(ptr_arg, "string") == 0) {
4515 if (!*(args[cur_arg + 1])) {
4516 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4517 file, linenum, args[0], args[1], ptr_arg);
4518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
4520 }
4521 struct tcpcheck_rule *tcpcheck;
4522
4523 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4524
4525 tcpcheck->action = TCPCHK_ACT_EXPECT;
4526 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4527 tcpcheck->string = strdup(args[cur_arg + 1]);
4528 tcpcheck->expect_regex = NULL;
4529 tcpcheck->inverse = inverse;
4530
4531 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4532 }
4533 else if (strcmp(ptr_arg, "rstring") == 0) {
4534 if (!*(args[cur_arg + 1])) {
4535 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4536 file, linenum, args[0], args[1], ptr_arg);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540 struct tcpcheck_rule *tcpcheck;
4541
4542 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4543
4544 tcpcheck->action = TCPCHK_ACT_EXPECT;
4545 tcpcheck->string_len = 0;
4546 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004547 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4548 error = NULL;
4549 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4550 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4551 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4552 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556 tcpcheck->inverse = inverse;
4557
4558 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4559 }
4560 else {
4561 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4562 file, linenum, args[0], args[1], ptr_arg);
4563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
4566 }
4567 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004568 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
4572 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004573 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004574 if (curproxy == &defproxy) {
4575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004578 }
4579
Willy Tarreaub80c2302007-11-30 20:51:32 +01004580 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004582
4583 if (strcmp(args[1], "fail") == 0) {
4584 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004585 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004586 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004590 }
4591
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004592 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4593 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4594 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004597 }
4598 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4599 }
4600 else {
4601 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004604 }
4605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606#ifdef TPROXY
4607 else if (!strcmp(args[0], "transparent")) {
4608 /* enable transparent proxy connections */
4609 curproxy->options |= PR_O_TRANSP;
4610 }
4611#endif
4612 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004613 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004615
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 if (*(args[1]) == 0) {
4617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 }
4621 curproxy->maxconn = atol(args[1]);
4622 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004623 else if (!strcmp(args[0], "backlog")) { /* backlog */
4624 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004626
4627 if (*(args[1]) == 0) {
4628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004631 }
4632 curproxy->backlog = atol(args[1]);
4633 }
Willy Tarreau86034312006-12-29 00:10:33 +01004634 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004637
Willy Tarreau86034312006-12-29 00:10:33 +01004638 if (*(args[1]) == 0) {
4639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004642 }
4643 curproxy->fullconn = atol(args[1]);
4644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4646 if (*(args[1]) == 0) {
4647 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004651 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4652 if (err) {
4653 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4654 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004657 }
4658 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
4660 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004661 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004662 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004663 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004664
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (curproxy == &defproxy) {
4666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 Tarreau977b8e42006-12-29 14:19:17 +01004670 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004672
Willy Tarreau902636f2013-03-10 19:44:48 +01004673 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004674 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004675 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004677 goto out;
4678 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004679
4680 proto = protocol_by_family(sk->ss_family);
4681 if (!proto || !proto->connect) {
4682 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4683 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
4686 }
4687
4688 if (port1 != port2) {
4689 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4690 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004694
4695 if (!port1) {
4696 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4697 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004701
Willy Tarreaud5191e72010-02-09 20:50:45 +01004702 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004703 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
4705 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004708
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004709 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4710 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004715 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004716 /**
4717 * The syntax for hash-type config element is
4718 * hash-type {map-based|consistent} [[<algo>] avalanche]
4719 *
4720 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4721 */
4722 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004723
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4725 err_code |= ERR_WARN;
4726
4727 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004728 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4729 }
4730 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004731 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4732 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004733 else if (strcmp(args[1], "avalanche") == 0) {
4734 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]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004737 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004738 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004739 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
4742 }
Bhaskar98634f02013-10-29 23:30:51 -04004743
4744 /* set the hash function to use */
4745 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004746 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004747 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004748
4749 /* if consistent with no argument, then avalanche modifier is also applied */
4750 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4751 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004752 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004753 /* set the hash function */
4754 if (!strcmp(args[2], "sdbm")) {
4755 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4756 }
4757 else if (!strcmp(args[2], "djb2")) {
4758 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004759 } else if (!strcmp(args[2], "wt6")) {
4760 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004761 }
4762 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004763 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 -05004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
4766 }
4767
4768 /* set the hash modifier */
4769 if (!strcmp(args[3], "avalanche")) {
4770 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4771 }
4772 else if (*args[3]) {
4773 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004777 }
William Lallemanda73203e2012-03-12 12:48:57 +01004778 }
William Lallemanda73203e2012-03-12 12:48:57 +01004779 else if (strcmp(args[0], "unique-id-format") == 0) {
4780 if (!*(args[1])) {
4781 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
William Lallemand3203ff42012-11-11 17:30:56 +01004785 if (*(args[2])) {
4786 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004790 free(curproxy->conf.uniqueid_format_string);
4791 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004792
Willy Tarreau62a61232013-04-12 18:13:46 +02004793 free(curproxy->conf.uif_file);
4794 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4795 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004796 }
William Lallemanda73203e2012-03-12 12:48:57 +01004797
4798 else if (strcmp(args[0], "unique-id-header") == 0) {
4799 if (!*(args[1])) {
4800 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
4804 free(curproxy->header_unique_id);
4805 curproxy->header_unique_id = strdup(args[1]);
4806 }
4807
William Lallemand723b73a2012-02-08 16:37:49 +01004808 else if (strcmp(args[0], "log-format") == 0) {
4809 if (!*(args[1])) {
4810 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
William Lallemand3203ff42012-11-11 17:30:56 +01004814 if (*(args[2])) {
4815 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
4818 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004819
Willy Tarreau62a61232013-04-12 18:13:46 +02004820 if (curproxy->conf.logformat_string != default_http_log_format &&
4821 curproxy->conf.logformat_string != default_tcp_log_format &&
4822 curproxy->conf.logformat_string != clf_http_log_format)
4823 free(curproxy->conf.logformat_string);
4824 curproxy->conf.logformat_string = strdup(args[1]);
4825
4826 free(curproxy->conf.lfs_file);
4827 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4828 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004829
4830 /* get a chance to improve log-format error reporting by
4831 * reporting the correct line-number when possible.
4832 */
4833 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4834 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4835 file, linenum, curproxy->id);
4836 err_code |= ERR_WARN;
4837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
William Lallemand723b73a2012-02-08 16:37:49 +01004839
William Lallemand0f99e342011-10-12 17:50:54 +02004840 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4841 /* delete previous herited or defined syslog servers */
4842 struct logsrv *back;
4843
4844 if (*(args[1]) != 0) {
4845 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
4848 }
4849
William Lallemand723b73a2012-02-08 16:37:49 +01004850 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4851 LIST_DEL(&tmplogsrv->list);
4852 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004853 }
4854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004856 struct logsrv *logsrv;
4857
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004859 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004860 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004861 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004862 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004863 LIST_INIT(&node->list);
4864 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
4867 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004868 struct sockaddr_storage *sk;
4869 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004870 int arg = 0;
4871 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004872
4873 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874
Willy Tarreau18324f52014-06-27 18:10:07 +02004875 /* just after the address, a length may be specified */
4876 if (strcmp(args[arg+2], "len") == 0) {
4877 len = atoi(args[arg+3]);
4878 if (len < 80 || len > 65535) {
4879 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4880 file, linenum, args[arg+3]);
4881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883 }
4884 logsrv->maxlen = len;
4885
4886 /* skip these two args */
4887 arg += 2;
4888 }
4889 else
4890 logsrv->maxlen = MAX_SYSLOG_LEN;
4891
4892 if (logsrv->maxlen > global.max_syslog_len) {
4893 global.max_syslog_len = logsrv->maxlen;
4894 logline = realloc(logline, global.max_syslog_len + 1);
4895 }
4896
4897 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004898 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004899 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904
William Lallemand0f99e342011-10-12 17:50:54 +02004905 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004906 if (*(args[arg+3])) {
4907 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004908 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004909 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
4912
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 }
4915
William Lallemand0f99e342011-10-12 17:50:54 +02004916 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004917 if (*(args[arg+4])) {
4918 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004919 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004920 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004924 }
4925 }
4926
Willy Tarreau902636f2013-03-10 19:44:48 +01004927 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004928 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004929 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004930 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004931 goto out;
4932 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004933
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004934 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004935
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004936 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004937 if (port1 != port2) {
4938 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4939 file, linenum, args[0], args[1]);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004944 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004945 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
William Lallemand0f99e342011-10-12 17:50:54 +02004947
4948 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950 else {
4951 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4952 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
4956 }
4957 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004958 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004959 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004960 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004961 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004962
Willy Tarreau977b8e42006-12-29 14:19:17 +01004963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004965
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004967 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4968 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004972
4973 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004974 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4975 free(curproxy->conn_src.iface_name);
4976 curproxy->conn_src.iface_name = NULL;
4977 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004978
Willy Tarreau902636f2013-03-10 19:44:48 +01004979 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004980 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004981 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004982 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004983 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004984 goto out;
4985 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004986
4987 proto = protocol_by_family(sk->ss_family);
4988 if (!proto || !proto->connect) {
4989 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004990 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004994
4995 if (port1 != port2) {
4996 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4997 file, linenum, args[0], args[1]);
4998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
5000 }
5001
Willy Tarreauef9a3602012-12-08 22:29:20 +01005002 curproxy->conn_src.source_addr = *sk;
5003 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005004
5005 cur_arg = 2;
5006 while (*(args[cur_arg])) {
5007 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005008#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5009#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005010 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005011 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5012 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005015 }
5016#endif
5017 if (!*args[cur_arg + 1]) {
5018 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5019 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005022 }
5023
5024 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005025 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5026 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005027 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005028 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5029 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005030 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5031 char *name, *end;
5032
5033 name = args[cur_arg+1] + 7;
5034 while (isspace(*name))
5035 name++;
5036
5037 end = name;
5038 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5039 end++;
5040
Willy Tarreauef9a3602012-12-08 22:29:20 +01005041 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5042 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5043 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5044 curproxy->conn_src.bind_hdr_len = end - name;
5045 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5046 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5047 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005048
5049 /* now look for an occurrence number */
5050 while (isspace(*end))
5051 end++;
5052 if (*end == ',') {
5053 end++;
5054 name = end;
5055 if (*end == '-')
5056 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005057 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005058 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005059 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005060 }
5061
Willy Tarreauef9a3602012-12-08 22:29:20 +01005062 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005063 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5064 " occurrences values smaller than %d.\n",
5065 file, linenum, MAX_HDR_HISTORY);
5066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
5068 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005069 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005070 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005071
Willy Tarreau902636f2013-03-10 19:44:48 +01005072 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005073 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005074 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005075 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005076 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005077 goto out;
5078 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005079
5080 proto = protocol_by_family(sk->ss_family);
5081 if (!proto || !proto->connect) {
5082 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5083 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
5086 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005087
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005088 if (port1 != port2) {
5089 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5090 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005094 curproxy->conn_src.tproxy_addr = *sk;
5095 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005096 }
5097 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005098#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005099 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005100#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005101#else /* no TPROXY support */
5102 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005103 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005106#endif
5107 cur_arg += 2;
5108 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005109 }
5110
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005111 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5112#ifdef SO_BINDTODEVICE
5113 if (!*args[cur_arg + 1]) {
5114 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5115 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005119 free(curproxy->conn_src.iface_name);
5120 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5121 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005122 global.last_checks |= LSTCHK_NETADM;
5123#else
5124 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5125 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005128#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005129 cur_arg += 2;
5130 continue;
5131 }
5132 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005133 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005134 err_code |= ERR_ALERT | ERR_FATAL;
5135 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005138 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5139 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5140 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5147 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151
5152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
5158 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005161 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
5165 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005167 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005168 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005175 args[0], args[1], NULL, (const char **)args+2);
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], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005186 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
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 Tarreaub8750a82006-09-03 09:56:00 +02005192 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005193 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005196 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005199
5200 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5201 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 +01005202 }
5203 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005205 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005206 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005208 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005209
5210 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5211 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 +01005212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5216 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220
5221 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005222 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005223 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
5227 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005229 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005230 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
5234 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005236 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005237 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
5241 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005243 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005244 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
5248 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005250 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005251 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005255 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005257 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005258 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005260 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005263 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005264
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 if (curproxy == &defproxy) {
5266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005270 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 if (*(args[1]) == 0) {
5274 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005278
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005279 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005280 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5281 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5282 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005286 err_code |= warnif_cond_conflicts(cond,
5287 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5288 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005289 }
5290 else if (*args[2]) {
5291 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5292 file, linenum, args[0], args[2]);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005297 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005298 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005299 wl->s = strdup(args[1]);
5300 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005301 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
5303 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005310
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005312 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005313 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
5317 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005319 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 }
5324 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005326 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005327 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
5331 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5334 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005340 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005341 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
5345 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005347 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005354 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005360 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005361
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 if (curproxy == &defproxy) {
5363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005367 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 if (*(args[1]) == 0) {
5371 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
5375
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005376 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005377 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5378 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5379 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005383 err_code |= warnif_cond_conflicts(cond,
5384 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5385 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005386 }
5387 else if (*args[2]) {
5388 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5389 file, linenum, args[0], args[2]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005394 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005395 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005396 wl->s = strdup(args[1]);
5397 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
5399 else if (!strcmp(args[0], "errorloc") ||
5400 !strcmp(args[0], "errorloc302") ||
5401 !strcmp(args[0], "errorloc303")) { /* error location */
5402 int errnum, errlen;
5403 char *err;
5404
Willy Tarreau977b8e42006-12-29 14:19:17 +01005405 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005406 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005407
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005409 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
5413
5414 errnum = atol(args[1]);
5415 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005416 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5417 err = malloc(errlen);
5418 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005420 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5421 err = malloc(errlen);
5422 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 }
5424
Willy Tarreau0f772532006-12-23 20:51:41 +01005425 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5426 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005427 chunk_destroy(&curproxy->errmsg[rc]);
5428 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005429 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005432
5433 if (rc >= HTTP_ERR_SIZE) {
5434 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5435 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005436 free(err);
5437 }
5438 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005439 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5440 int errnum, errlen, fd;
5441 char *err;
5442 struct stat stat;
5443
5444 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005446
5447 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005448 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005451 }
5452
5453 fd = open(args[2], O_RDONLY);
5454 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5455 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5456 file, linenum, args[2], args[1]);
5457 if (fd >= 0)
5458 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005461 }
5462
Willy Tarreau27a674e2009-08-17 07:23:33 +02005463 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005464 errlen = stat.st_size;
5465 } else {
5466 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005467 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005469 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005470 }
5471
5472 err = malloc(errlen); /* malloc() must succeed during parsing */
5473 errnum = read(fd, err, errlen);
5474 if (errnum != errlen) {
5475 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5476 file, linenum, args[2], args[1]);
5477 close(fd);
5478 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005481 }
5482 close(fd);
5483
5484 errnum = atol(args[1]);
5485 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5486 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005487 chunk_destroy(&curproxy->errmsg[rc]);
5488 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005489 break;
5490 }
5491 }
5492
5493 if (rc >= HTTP_ERR_SIZE) {
5494 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5495 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005496 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005497 free(err);
5498 }
5499 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005500 else if (!strcmp(args[0], "compression")) {
5501 struct comp *comp;
5502 if (curproxy->comp == NULL) {
5503 comp = calloc(1, sizeof(struct comp));
5504 curproxy->comp = comp;
5505 } else {
5506 comp = curproxy->comp;
5507 }
5508
5509 if (!strcmp(args[1], "algo")) {
5510 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005511 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005512
William Lallemand82fe75c2012-10-23 10:25:10 +02005513 cur_arg = 2;
5514 if (!*args[cur_arg]) {
5515 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5516 file, linenum, args[0]);
5517 err_code |= ERR_ALERT | ERR_FATAL;
5518 goto out;
5519 }
5520 while (*(args[cur_arg])) {
5521 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5522 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5523 file, linenum, args[0], args[cur_arg]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
William Lallemand552df672012-11-07 13:21:47 +01005527 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5528 curproxy->comp->algos->end(&ctx);
5529 } else {
5530 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5531 file, linenum, args[0], args[cur_arg]);
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005535 cur_arg ++;
5536 continue;
5537 }
5538 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005539 else if (!strcmp(args[1], "offload")) {
5540 comp->offload = 1;
5541 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005542 else if (!strcmp(args[1], "type")) {
5543 int cur_arg;
5544 cur_arg = 2;
5545 if (!*args[cur_arg]) {
5546 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5547 file, linenum, args[0]);
5548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
5551 while (*(args[cur_arg])) {
5552 comp_append_type(comp, args[cur_arg]);
5553 cur_arg ++;
5554 continue;
5555 }
5556 }
5557 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005558 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005559 file, linenum, args[0]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005565 struct cfg_kw_list *kwl;
5566 int index;
5567
5568 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5569 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5570 if (kwl->kw[index].section != CFG_LISTEN)
5571 continue;
5572 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5573 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005574 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005575 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005576 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005579 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005580 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005581 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_WARN;
5583 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005584 }
Willy Tarreau93893792009-07-23 13:19:11 +02005585 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005586 }
5587 }
5588 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005589
Willy Tarreau6daf3432008-01-22 16:44:08 +01005590 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
Willy Tarreau93893792009-07-23 13:19:11 +02005594 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005595 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005596 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597}
5598
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005599int
5600cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5601{
5602
5603 int err_code = 0;
5604 const char *err;
5605
5606 if (!strcmp(args[0], "userlist")) { /* new userlist */
5607 struct userlist *newul;
5608
5609 if (!*args[1]) {
5610 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5611 file, linenum, args[0]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
5616 err = invalid_char(args[1]);
5617 if (err) {
5618 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5619 file, linenum, *err, args[0], args[1]);
5620 err_code |= ERR_ALERT | ERR_FATAL;
5621 goto out;
5622 }
5623
5624 for (newul = userlist; newul; newul = newul->next)
5625 if (!strcmp(newul->name, args[1])) {
5626 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5627 file, linenum, args[1]);
5628 err_code |= ERR_WARN;
5629 goto out;
5630 }
5631
5632 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5633 if (!newul) {
5634 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5635 err_code |= ERR_ALERT | ERR_ABORT;
5636 goto out;
5637 }
5638
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005639 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005640 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005641 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5642 err_code |= ERR_ALERT | ERR_ABORT;
5643 goto out;
5644 }
5645
5646 newul->next = userlist;
5647 userlist = newul;
5648
5649 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005650 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005651 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005652 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005653
5654 if (!*args[1]) {
5655 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5656 file, linenum, args[0]);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660
5661 err = invalid_char(args[1]);
5662 if (err) {
5663 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5664 file, linenum, *err, args[0], args[1]);
5665 err_code |= ERR_ALERT | ERR_FATAL;
5666 goto out;
5667 }
5668
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005669 for (ag = userlist->groups; ag; ag = ag->next)
5670 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005671 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5672 file, linenum, args[1], userlist->name);
5673 err_code |= ERR_ALERT;
5674 goto out;
5675 }
5676
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005677 ag = calloc(1, sizeof(*ag));
5678 if (!ag) {
5679 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5680 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005681 goto out;
5682 }
5683
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005684 ag->name = strdup(args[1]);
5685 if (!ag) {
5686 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5687 err_code |= ERR_ALERT | ERR_ABORT;
5688 goto out;
5689 }
5690
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005691 cur_arg = 2;
5692
5693 while (*args[cur_arg]) {
5694 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005695 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005696 cur_arg += 2;
5697 continue;
5698 } else {
5699 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5700 file, linenum, args[0]);
5701 err_code |= ERR_ALERT | ERR_FATAL;
5702 goto out;
5703 }
5704 }
5705
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005706 ag->next = userlist->groups;
5707 userlist->groups = ag;
5708
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005709 } else if (!strcmp(args[0], "user")) { /* new user */
5710 struct auth_users *newuser;
5711 int cur_arg;
5712
5713 if (!*args[1]) {
5714 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5715 file, linenum, args[0]);
5716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
5719
5720 for (newuser = userlist->users; newuser; newuser = newuser->next)
5721 if (!strcmp(newuser->user, args[1])) {
5722 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5723 file, linenum, args[1], userlist->name);
5724 err_code |= ERR_ALERT;
5725 goto out;
5726 }
5727
5728 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5729 if (!newuser) {
5730 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5731 err_code |= ERR_ALERT | ERR_ABORT;
5732 goto out;
5733 }
5734
5735 newuser->user = strdup(args[1]);
5736
5737 newuser->next = userlist->users;
5738 userlist->users = newuser;
5739
5740 cur_arg = 2;
5741
5742 while (*args[cur_arg]) {
5743 if (!strcmp(args[cur_arg], "password")) {
5744#ifndef CONFIG_HAP_CRYPT
5745 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5746 file, linenum);
5747 err_code |= ERR_ALERT;
5748#endif
5749 newuser->pass = strdup(args[cur_arg + 1]);
5750 cur_arg += 2;
5751 continue;
5752 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5753 newuser->pass = strdup(args[cur_arg + 1]);
5754 newuser->flags |= AU_O_INSECURE;
5755 cur_arg += 2;
5756 continue;
5757 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005758 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005759 cur_arg += 2;
5760 continue;
5761 } else {
5762 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5763 file, linenum, args[0]);
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
5766 }
5767 }
5768 } else {
5769 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5770 err_code |= ERR_ALERT | ERR_FATAL;
5771 }
5772
5773out:
5774 return err_code;
5775}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776
5777/*
5778 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005779 * Returns the error code, 0 if OK, or any combination of :
5780 * - ERR_ABORT: must abort ASAP
5781 * - ERR_FATAL: we can continue parsing but not start the service
5782 * - ERR_WARN: a warning has been emitted
5783 * - ERR_ALERT: an alert has been emitted
5784 * Only the two first ones can stop processing, the two others are just
5785 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005787int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005789 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 FILE *f;
5791 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005792 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005793 struct cfg_section *cs = NULL;
5794 struct cfg_section *ics;
5795
5796 /* Register internal sections */
5797 if (!cfg_register_section("listen", cfg_parse_listen) ||
5798 !cfg_register_section("frontend", cfg_parse_listen) ||
5799 !cfg_register_section("backend", cfg_parse_listen) ||
5800 !cfg_register_section("ruleset", cfg_parse_listen) ||
5801 !cfg_register_section("defaults", cfg_parse_listen) ||
5802 !cfg_register_section("global", cfg_parse_global) ||
5803 !cfg_register_section("userlist", cfg_parse_users) ||
5804 !cfg_register_section("peers", cfg_parse_peers))
5805 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 if ((f=fopen(file,"r")) == NULL)
5808 return -1;
5809
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005810 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005811 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005812 char *end;
5813 char *args[MAX_LINE_ARGS + 1];
5814 char *line = thisline;
5815
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 linenum++;
5817
5818 end = line + strlen(line);
5819
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005820 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5821 /* Check if we reached the limit and the last char is not \n.
5822 * Watch out for the last line without the terminating '\n'!
5823 */
5824 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005825 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005826 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005827 }
5828
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005830 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 line++;
5832
5833 arg = 0;
5834 args[arg] = line;
5835
5836 while (*line && arg < MAX_LINE_ARGS) {
5837 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5838 * C equivalent value. Other combinations left unchanged (eg: \1).
5839 */
5840 if (*line == '\\') {
5841 int skip = 0;
5842 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5843 *line = line[1];
5844 skip = 1;
5845 }
5846 else if (line[1] == 'r') {
5847 *line = '\r';
5848 skip = 1;
5849 }
5850 else if (line[1] == 'n') {
5851 *line = '\n';
5852 skip = 1;
5853 }
5854 else if (line[1] == 't') {
5855 *line = '\t';
5856 skip = 1;
5857 }
5858 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005859 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 unsigned char hex1, hex2;
5861 hex1 = toupper(line[2]) - '0';
5862 hex2 = toupper(line[3]) - '0';
5863 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5864 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5865 *line = (hex1<<4) + hex2;
5866 skip = 3;
5867 }
5868 else {
5869 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871 }
5872 }
5873 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005874 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875 end -= skip;
5876 }
5877 line++;
5878 }
5879 else if (*line == '#' || *line == '\n' || *line == '\r') {
5880 /* end of string, end of loop */
5881 *line = 0;
5882 break;
5883 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005884 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005886 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005887 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 line++;
5889 args[++arg] = line;
5890 }
5891 else {
5892 line++;
5893 }
5894 }
5895
5896 /* empty line */
5897 if (!**args)
5898 continue;
5899
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005900 if (*line) {
5901 /* we had to stop due to too many args.
5902 * Let's terminate the string, print the offending part then cut the
5903 * last arg.
5904 */
5905 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5906 line++;
5907 *line = '\0';
5908
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005909 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005910 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005911 err_code |= ERR_ALERT | ERR_FATAL;
5912 args[arg] = line;
5913 }
5914
Willy Tarreau540abe42007-05-02 20:50:16 +02005915 /* zero out remaining args and ensure that at least one entry
5916 * is zeroed out.
5917 */
5918 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 args[arg] = line;
5920 }
5921
Willy Tarreau3842f002009-06-14 11:39:52 +02005922 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005923 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005924 char *tmp;
5925
Willy Tarreau3842f002009-06-14 11:39:52 +02005926 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005927 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005928 for (arg=0; *args[arg+1]; arg++)
5929 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005930 *tmp = '\0'; // fix the next arg to \0
5931 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005932 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005933 else if (!strcmp(args[0], "default")) {
5934 kwm = KWM_DEF;
5935 for (arg=0; *args[arg+1]; arg++)
5936 args[arg] = args[arg+1]; // shift args after inversion
5937 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005938
William Lallemand0f99e342011-10-12 17:50:54 +02005939 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5940 strcmp(args[0], "log") != 0) {
5941 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005942 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005943 }
5944
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005945 /* detect section start */
5946 list_for_each_entry(ics, &sections, list) {
5947 if (strcmp(args[0], ics->section_name) == 0) {
5948 cursection = ics->section_name;
5949 cs = ics;
5950 break;
5951 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005952 }
5953
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005955 if (cs)
5956 err_code |= cs->section_parser(file, linenum, args, kwm);
5957 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005958 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005959 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005961
5962 if (err_code & ERR_ABORT)
5963 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005965 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005967 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005968}
5969
Willy Tarreaubb925012009-07-23 13:36:36 +02005970/*
5971 * Returns the error code, 0 if OK, or any combination of :
5972 * - ERR_ABORT: must abort ASAP
5973 * - ERR_FATAL: we can continue parsing but not start the service
5974 * - ERR_WARN: a warning has been emitted
5975 * - ERR_ALERT: an alert has been emitted
5976 * Only the two first ones can stop processing, the two others are just
5977 * indicators.
5978 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979int check_config_validity()
5980{
5981 int cfgerr = 0;
5982 struct proxy *curproxy = NULL;
5983 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005984 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005985 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005986 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005988 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 /*
5990 * Now, check for the integrity of all that we have collected.
5991 */
5992
5993 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005994 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995
Willy Tarreau193b8c62012-11-22 00:17:38 +01005996 if (!global.tune.max_http_hdr)
5997 global.tune.max_http_hdr = MAX_HTTP_HDR;
5998
5999 if (!global.tune.cookie_len)
6000 global.tune.cookie_len = CAPTURE_LEN;
6001
6002 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6003
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006004 /* Post initialisation of the users and groups lists. */
6005 err_code = userlist_postinit();
6006 if (err_code != ERR_NONE)
6007 goto out;
6008
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006009 /* first, we will invert the proxy list order */
6010 curproxy = NULL;
6011 while (proxy) {
6012 struct proxy *next;
6013
6014 next = proxy->next;
6015 proxy->next = curproxy;
6016 curproxy = proxy;
6017 if (!next)
6018 break;
6019 proxy = next;
6020 }
6021
Willy Tarreaubaaee002006-06-26 02:48:02 +02006022 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006023 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006024 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006025 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006026 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006027 struct http_req_rule *hrqrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006028 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006029 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006030 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006031
Willy Tarreau050536d2012-10-04 08:47:34 +02006032 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006033 /* proxy ID not set, use automatic numbering with first
6034 * spare entry starting with next_pxid.
6035 */
6036 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6037 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6038 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006039 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006040 next_pxid++;
6041
Willy Tarreau55ea7572007-06-17 19:56:27 +02006042
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006044 /* ensure we don't keep listeners uselessly bound */
6045 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006046 curproxy = curproxy->next;
6047 continue;
6048 }
6049
Willy Tarreau102df612014-05-07 23:56:38 +02006050 /* Check multi-process mode compatibility for the current proxy */
6051
6052 if (curproxy->bind_proc) {
6053 /* an explicit bind-process was specified, let's check how many
6054 * processes remain.
6055 */
6056 nbproc = popcount(curproxy->bind_proc);
6057
6058 curproxy->bind_proc &= nbits(global.nbproc);
6059 if (!curproxy->bind_proc && nbproc == 1) {
6060 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);
6061 curproxy->bind_proc = 1;
6062 }
6063 else if (!curproxy->bind_proc && nbproc > 1) {
6064 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);
6065 curproxy->bind_proc = 0;
6066 }
6067 }
6068
Willy Tarreau3d209582014-05-09 17:06:11 +02006069 /* check and reduce the bind-proc of each listener */
6070 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6071 unsigned long mask;
6072
6073 if (!bind_conf->bind_proc)
6074 continue;
6075
6076 mask = nbits(global.nbproc);
6077 if (curproxy->bind_proc)
6078 mask &= curproxy->bind_proc;
6079 /* mask cannot be null here thanks to the previous checks */
6080
6081 nbproc = popcount(bind_conf->bind_proc);
6082 bind_conf->bind_proc &= mask;
6083
6084 if (!bind_conf->bind_proc && nbproc == 1) {
6085 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",
6086 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6087 bind_conf->bind_proc = mask & ~(mask - 1);
6088 }
6089 else if (!bind_conf->bind_proc && nbproc > 1) {
6090 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",
6091 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6092 bind_conf->bind_proc = 0;
6093 }
6094 }
6095
Willy Tarreau102df612014-05-07 23:56:38 +02006096 /* here, if bind_proc is null, it means no limit, otherwise it's explicit.
6097 * We now check how many processes the proxy will effectively run on.
6098 */
6099
6100 nbproc = global.nbproc;
6101 if (curproxy->bind_proc)
6102 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
6103
6104 if (global.nbproc > 1 && curproxy->table.peers.name) {
6105 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6106 curproxy->id);
6107 cfgerr++;
6108 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006109
Willy Tarreauff01a212009-03-15 13:46:16 +01006110 switch (curproxy->mode) {
6111 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006112 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006113 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006114 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6115 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006116 cfgerr++;
6117 }
6118
6119 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006120 Warning("config : servers will be ignored for %s '%s'.\n",
6121 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006122 break;
6123
6124 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006125 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006126 break;
6127
6128 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006129 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006130 break;
6131 }
6132
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006133 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006134 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006135 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006136 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6137 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006138 cfgerr++;
6139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006141 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006142 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6143 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006144 cfgerr++;
6145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006147 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006148 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6149 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006150 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006151 }
6152 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006153 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006154 /* If no LB algo is set in a backend, and we're not in
6155 * transparent mode, dispatch mode nor proxy mode, we
6156 * want to use balance roundrobin by default.
6157 */
6158 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6159 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 }
6161 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006162
Willy Tarreau1620ec32011-08-06 17:05:02 +02006163 if (curproxy->options & PR_O_DISPATCH)
6164 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6165 else if (curproxy->options & PR_O_HTTP_PROXY)
6166 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6167 else if (curproxy->options & PR_O_TRANSP)
6168 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006169
Willy Tarreau1620ec32011-08-06 17:05:02 +02006170 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6171 if (curproxy->options & PR_O_DISABLE404) {
6172 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6173 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6174 err_code |= ERR_WARN;
6175 curproxy->options &= ~PR_O_DISABLE404;
6176 }
6177 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6178 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6179 "send-state", proxy_type_str(curproxy), curproxy->id);
6180 err_code |= ERR_WARN;
6181 curproxy->options &= ~PR_O2_CHK_SNDST;
6182 }
Willy Tarreauef781042010-01-27 11:53:01 +01006183 }
6184
Simon Horman98637e52014-06-20 12:30:16 +09006185 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6186 if (!global.external_check) {
6187 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6188 curproxy->id, "option external-check");
6189 cfgerr++;
6190 }
6191 if (!curproxy->check_command) {
6192 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6193 curproxy->id, "option external-check");
6194 cfgerr++;
6195 }
6196 }
6197
6198 if (curproxy->check_command) {
6199 int clear = 0;
6200 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6201 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6202 "external-check command", proxy_type_str(curproxy), curproxy->id);
6203 err_code |= ERR_WARN;
6204 clear = 1;
6205 }
6206 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6207 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6208 curproxy->id, "external-check command");
6209 cfgerr++;
6210 }
6211 if (clear) {
6212 free(curproxy->check_command);
6213 curproxy->check_command = NULL;
6214 }
6215 }
6216
6217 if (curproxy->check_path) {
6218 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6219 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6220 "external-check path", proxy_type_str(curproxy), curproxy->id);
6221 err_code |= ERR_WARN;
6222 free(curproxy->check_path);
6223 curproxy->check_path = NULL;
6224 }
6225 }
6226
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006227 /* if a default backend was specified, let's find it */
6228 if (curproxy->defbe.name) {
6229 struct proxy *target;
6230
Alex Williams96532db2009-11-01 21:27:13 -05006231 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006232 if (!target) {
6233 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6234 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006235 cfgerr++;
6236 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006237 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6238 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006239 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006240 } else {
6241 free(curproxy->defbe.name);
6242 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006243 /* we force the backend to be present on at least all of
6244 * the frontend's processes.
6245 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006246 if (target->bind_proc)
6247 target->bind_proc = curproxy->bind_proc ?
6248 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006249
6250 /* Emit a warning if this proxy also has some servers */
6251 if (curproxy->srv) {
6252 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6253 curproxy->id);
6254 err_code |= ERR_WARN;
6255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006256 }
6257 }
6258
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006259 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006260 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6261 /* map jump target for ACT_SETBE in req_rep chain */
6262 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006263 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006264 struct proxy *target;
6265
Willy Tarreaua496b602006-12-17 23:15:24 +01006266 if (exp->action != ACT_SETBE)
6267 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006268
Alex Williams96532db2009-11-01 21:27:13 -05006269 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006270 if (!target) {
6271 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6272 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006273 cfgerr++;
6274 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006275 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6276 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006277 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006278 } else {
6279 free((void *)exp->replace);
6280 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006281 /* we force the backend to be present on at least all of
6282 * the frontend's processes.
6283 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006284 if (target->bind_proc)
6285 target->bind_proc = curproxy->bind_proc ?
6286 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006287 }
6288 }
6289 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006290
6291 /* find the target proxy for 'use_backend' rules */
6292 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006293 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006294 struct logformat_node *node;
6295 char *pxname;
6296
6297 /* Try to parse the string as a log format expression. If the result
6298 * of the parsing is only one entry containing a simple string, then
6299 * it's a standard string corresponding to a static rule, thus the
6300 * parsing is cancelled and be.name is restored to be resolved.
6301 */
6302 pxname = rule->be.name;
6303 LIST_INIT(&rule->be.expr);
6304 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6305 curproxy->conf.args.file, curproxy->conf.args.line);
6306 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6307
6308 if (!LIST_ISEMPTY(&rule->be.expr)) {
6309 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6310 rule->dynamic = 1;
6311 free(pxname);
6312 continue;
6313 }
6314 /* simple string: free the expression and fall back to static rule */
6315 free(node->arg);
6316 free(node);
6317 }
6318
6319 rule->dynamic = 0;
6320 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006321
Alex Williams96532db2009-11-01 21:27:13 -05006322 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006323
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006324 if (!target) {
6325 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6326 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006327 cfgerr++;
6328 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006329 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6330 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006331 cfgerr++;
6332 } else {
6333 free((void *)rule->be.name);
6334 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006335 /* we force the backend to be present on at least all of
6336 * the frontend's processes.
6337 */
Willy Tarreau3507d5d2014-05-09 13:54:22 +02006338 if (target->bind_proc)
6339 target->bind_proc = curproxy->bind_proc ?
6340 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006341 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006342 }
6343
6344 /* find the target proxy for 'use_backend' rules */
6345 list_for_each_entry(srule, &curproxy->server_rules, list) {
6346 struct server *target = findserver(curproxy, srule->srv.name);
6347
6348 if (!target) {
6349 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6350 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6351 cfgerr++;
6352 continue;
6353 }
6354 free((void *)srule->srv.name);
6355 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006356 }
6357
Emeric Brunb982a3d2010-01-04 15:45:53 +01006358 /* find the target table for 'stick' rules */
6359 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6360 struct proxy *target;
6361
Emeric Brun1d33b292010-01-04 15:47:17 +01006362 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6363 if (mrule->flags & STK_IS_STORE)
6364 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6365
Emeric Brunb982a3d2010-01-04 15:45:53 +01006366 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006367 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006368 else
6369 target = curproxy;
6370
6371 if (!target) {
6372 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6373 curproxy->id, mrule->table.name);
6374 cfgerr++;
6375 }
6376 else if (target->table.size == 0) {
6377 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6378 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6379 cfgerr++;
6380 }
Willy Tarreau12785782012-04-27 21:37:17 +02006381 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6382 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006383 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6384 cfgerr++;
6385 }
6386 else {
6387 free((void *)mrule->table.name);
6388 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006389 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006390 }
6391 }
6392
6393 /* find the target table for 'store response' rules */
6394 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6395 struct proxy *target;
6396
Emeric Brun1d33b292010-01-04 15:47:17 +01006397 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6398
Emeric Brunb982a3d2010-01-04 15:45:53 +01006399 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006400 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006401 else
6402 target = curproxy;
6403
6404 if (!target) {
6405 Alert("Proxy '%s': unable to find store table '%s'.\n",
6406 curproxy->id, mrule->table.name);
6407 cfgerr++;
6408 }
6409 else if (target->table.size == 0) {
6410 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6411 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6412 cfgerr++;
6413 }
Willy Tarreau12785782012-04-27 21:37:17 +02006414 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6415 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006416 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6417 cfgerr++;
6418 }
6419 else {
6420 free((void *)mrule->table.name);
6421 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006422 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006423 }
6424 }
6425
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006426 /* find the target table for 'tcp-request' layer 4 rules */
6427 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6428 struct proxy *target;
6429
Willy Tarreaub4c84932013-07-23 19:15:30 +02006430 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006431 continue;
6432
6433 if (trule->act_prm.trk_ctr.table.n)
6434 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6435 else
6436 target = curproxy;
6437
6438 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006439 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6440 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006441 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006442 cfgerr++;
6443 }
6444 else if (target->table.size == 0) {
6445 Alert("Proxy '%s': table '%s' used but not configured.\n",
6446 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6447 cfgerr++;
6448 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006449 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6450 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6451 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 +01006452 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006453 cfgerr++;
6454 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006455 else {
6456 free(trule->act_prm.trk_ctr.table.n);
6457 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006458 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006459 * to pass a list of counters to track and allocate them right here using
6460 * stktable_alloc_data_type().
6461 */
6462 }
6463 }
6464
Willy Tarreaud1f96522010-08-03 19:34:32 +02006465 /* find the target table for 'tcp-request' layer 6 rules */
6466 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6467 struct proxy *target;
6468
Willy Tarreaub4c84932013-07-23 19:15:30 +02006469 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006470 continue;
6471
6472 if (trule->act_prm.trk_ctr.table.n)
6473 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6474 else
6475 target = curproxy;
6476
6477 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006478 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6479 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006480 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006481 cfgerr++;
6482 }
6483 else if (target->table.size == 0) {
6484 Alert("Proxy '%s': table '%s' used but not configured.\n",
6485 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6486 cfgerr++;
6487 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006488 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6489 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6490 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 +01006491 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006492 cfgerr++;
6493 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006494 else {
6495 free(trule->act_prm.trk_ctr.table.n);
6496 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006497 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006498 * to pass a list of counters to track and allocate them right here using
6499 * stktable_alloc_data_type().
6500 */
6501 }
6502 }
6503
Willy Tarreau09448f72014-06-25 18:12:15 +02006504 /* find the target table for 'http-request' layer 7 rules */
6505 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6506 struct proxy *target;
6507
6508 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6509 continue;
6510
6511 if (hrqrule->act_prm.trk_ctr.table.n)
6512 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6513 else
6514 target = curproxy;
6515
6516 if (!target) {
6517 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6518 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6519 http_req_trk_idx(hrqrule->action));
6520 cfgerr++;
6521 }
6522 else if (target->table.size == 0) {
6523 Alert("Proxy '%s': table '%s' used but not configured.\n",
6524 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6525 cfgerr++;
6526 }
6527 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6528 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6529 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6530 http_req_trk_idx(hrqrule->action));
6531 cfgerr++;
6532 }
6533 else {
6534 free(hrqrule->act_prm.trk_ctr.table.n);
6535 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6536 /* Note: if we decide to enhance the track-sc syntax, we may be able
6537 * to pass a list of counters to track and allocate them right here using
6538 * stktable_alloc_data_type().
6539 */
6540 }
6541 }
6542
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006543 /* move any "block" rules at the beginning of the http-request rules */
6544 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6545 /* insert block_rules into http_req_rules at the beginning */
6546 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6547 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6548 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6549 curproxy->http_req_rules.n = curproxy->block_rules.n;
6550 LIST_INIT(&curproxy->block_rules);
6551 }
6552
Emeric Brun32da3c42010-09-23 18:39:19 +02006553 if (curproxy->table.peers.name) {
6554 struct peers *curpeers = peers;
6555
6556 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6557 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6558 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006559 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006560 break;
6561 }
6562 }
6563
6564 if (!curpeers) {
6565 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6566 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006567 free((void *)curproxy->table.peers.name);
6568 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006569 cfgerr++;
6570 }
6571 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006572 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6573 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006574 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006575 cfgerr++;
6576 }
6577 }
6578
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006579 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006580 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006581 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6582 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6583 "proxy", curproxy->id);
6584 cfgerr++;
6585 goto out_uri_auth_compat;
6586 }
6587
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006588 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006589 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006590 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006591 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006592
Willy Tarreau95fa4692010-02-01 13:05:50 +01006593 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6594 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006595
6596 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006597 uri_auth_compat_req[i++] = "realm";
6598 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6599 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006600
Willy Tarreau95fa4692010-02-01 13:05:50 +01006601 uri_auth_compat_req[i++] = "unless";
6602 uri_auth_compat_req[i++] = "{";
6603 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6604 uri_auth_compat_req[i++] = "}";
6605 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006606
Willy Tarreauff011f22011-01-06 17:51:27 +01006607 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6608 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006609 cfgerr++;
6610 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006611 }
6612
Willy Tarreauff011f22011-01-06 17:51:27 +01006613 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006614
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006615 if (curproxy->uri_auth->auth_realm) {
6616 free(curproxy->uri_auth->auth_realm);
6617 curproxy->uri_auth->auth_realm = NULL;
6618 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006619
6620 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006621 }
6622out_uri_auth_compat:
6623
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006624 /* compile the log format */
6625 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006626 if (curproxy->conf.logformat_string != default_http_log_format &&
6627 curproxy->conf.logformat_string != default_tcp_log_format &&
6628 curproxy->conf.logformat_string != clf_http_log_format)
6629 free(curproxy->conf.logformat_string);
6630 curproxy->conf.logformat_string = NULL;
6631 free(curproxy->conf.lfs_file);
6632 curproxy->conf.lfs_file = NULL;
6633 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006634 }
6635
Willy Tarreau62a61232013-04-12 18:13:46 +02006636 if (curproxy->conf.logformat_string) {
6637 curproxy->conf.args.ctx = ARGC_LOG;
6638 curproxy->conf.args.file = curproxy->conf.lfs_file;
6639 curproxy->conf.args.line = curproxy->conf.lfs_line;
6640 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006641 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006642 curproxy->conf.args.file = NULL;
6643 curproxy->conf.args.line = 0;
6644 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006645
Willy Tarreau62a61232013-04-12 18:13:46 +02006646 if (curproxy->conf.uniqueid_format_string) {
6647 curproxy->conf.args.ctx = ARGC_UIF;
6648 curproxy->conf.args.file = curproxy->conf.uif_file;
6649 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006650 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006651 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6652 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006653 curproxy->conf.args.file = NULL;
6654 curproxy->conf.args.line = 0;
6655 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006656
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006657 /* only now we can check if some args remain unresolved.
6658 * This must be done after the users and groups resolution.
6659 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006660 cfgerr += smp_resolve_args(curproxy);
6661 if (!cfgerr)
6662 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006663
Willy Tarreau2738a142006-07-08 17:28:09 +02006664 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006665 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006666 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006667 (!curproxy->timeout.connect ||
6668 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006669 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006670 " | While not properly invalid, you will certainly encounter various problems\n"
6671 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006672 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006673 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006674 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006675 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006676
Willy Tarreau1fa31262007-12-03 00:36:16 +01006677 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6678 * We must still support older configurations, so let's find out whether those
6679 * parameters have been set or must be copied from contimeouts.
6680 */
6681 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006682 if (!curproxy->timeout.tarpit ||
6683 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006684 /* tarpit timeout not set. We search in the following order:
6685 * default.tarpit, curr.connect, default.connect.
6686 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006687 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006688 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006689 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006690 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006691 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006692 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006693 }
6694 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006695 (!curproxy->timeout.queue ||
6696 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006697 /* queue timeout not set. We search in the following order:
6698 * default.queue, curr.connect, default.connect.
6699 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006700 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006701 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006702 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006703 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006704 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006705 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006706 }
6707 }
6708
Willy Tarreau1620ec32011-08-06 17:05:02 +02006709 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006710 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6711 curproxy->check_req = (char *)malloc(curproxy->check_len);
6712 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006713 }
6714
Willy Tarreau215663d2014-06-13 18:30:23 +02006715 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6716 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6717 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6718 proxy_type_str(curproxy), curproxy->id);
6719 err_code |= ERR_WARN;
6720 }
6721
Willy Tarreau193b8c62012-11-22 00:17:38 +01006722 /* ensure that cookie capture length is not too large */
6723 if (curproxy->capture_len >= global.tune.cookie_len) {
6724 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6725 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6726 err_code |= ERR_WARN;
6727 curproxy->capture_len = global.tune.cookie_len - 1;
6728 }
6729
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006730 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006731 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006732 curproxy->req_cap_pool = create_pool("ptrcap",
6733 curproxy->nb_req_cap * sizeof(char *),
6734 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006735 }
6736
6737 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006738 curproxy->rsp_cap_pool = create_pool("ptrcap",
6739 curproxy->nb_rsp_cap * sizeof(char *),
6740 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006741 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006742
Willy Tarreaubaaee002006-06-26 02:48:02 +02006743 /* first, we will invert the servers list order */
6744 newsrv = NULL;
6745 while (curproxy->srv) {
6746 struct server *next;
6747
6748 next = curproxy->srv->next;
6749 curproxy->srv->next = newsrv;
6750 newsrv = curproxy->srv;
6751 if (!next)
6752 break;
6753 curproxy->srv = next;
6754 }
6755
Willy Tarreau17edc812014-01-03 12:14:34 +01006756 /* Check that no server name conflicts. This causes trouble in the stats.
6757 * We only emit a warning for the first conflict affecting each server,
6758 * in order to avoid combinatory explosion if all servers have the same
6759 * name. We do that only for servers which do not have an explicit ID,
6760 * because these IDs were made also for distinguishing them and we don't
6761 * want to annoy people who correctly manage them.
6762 */
6763 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6764 struct server *other_srv;
6765
6766 if (newsrv->puid)
6767 continue;
6768
6769 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6770 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6771 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6772 newsrv->conf.file, newsrv->conf.line,
6773 proxy_type_str(curproxy), curproxy->id,
6774 newsrv->id, other_srv->conf.line);
6775 break;
6776 }
6777 }
6778 }
6779
Willy Tarreaudd701652010-05-25 23:03:02 +02006780 /* assign automatic UIDs to servers which don't have one yet */
6781 next_id = 1;
6782 newsrv = curproxy->srv;
6783 while (newsrv != NULL) {
6784 if (!newsrv->puid) {
6785 /* server ID not set, use automatic numbering with first
6786 * spare entry starting with next_svid.
6787 */
6788 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6789 newsrv->conf.id.key = newsrv->puid = next_id;
6790 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6791 }
6792 next_id++;
6793 newsrv = newsrv->next;
6794 }
6795
Willy Tarreau20697042007-11-15 23:26:18 +01006796 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006797 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006798
Willy Tarreau62c3be22012-01-20 13:12:32 +01006799 /*
6800 * If this server supports a maxconn parameter, it needs a dedicated
6801 * tasks to fill the emptied slots when a connection leaves.
6802 * Also, resolve deferred tracking dependency if needed.
6803 */
6804 newsrv = curproxy->srv;
6805 while (newsrv != NULL) {
6806 if (newsrv->minconn > newsrv->maxconn) {
6807 /* Only 'minconn' was specified, or it was higher than or equal
6808 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6809 * this will avoid further useless expensive computations.
6810 */
6811 newsrv->maxconn = newsrv->minconn;
6812 } else if (newsrv->maxconn && !newsrv->minconn) {
6813 /* minconn was not specified, so we set it to maxconn */
6814 newsrv->minconn = newsrv->maxconn;
6815 }
6816
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006817#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006818 if (newsrv->use_ssl || newsrv->check.use_ssl)
6819 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006820#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006821
Willy Tarreau2f075e92013-12-03 11:11:34 +01006822 /* set the check type on the server */
6823 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6824
Willy Tarreau62c3be22012-01-20 13:12:32 +01006825 if (newsrv->trackit) {
6826 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006827 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006828 char *pname, *sname;
6829
6830 pname = newsrv->trackit;
6831 sname = strrchr(pname, '/');
6832
6833 if (sname)
6834 *sname++ = '\0';
6835 else {
6836 sname = pname;
6837 pname = NULL;
6838 }
6839
6840 if (pname) {
6841 px = findproxy(pname, PR_CAP_BE);
6842 if (!px) {
6843 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6844 proxy_type_str(curproxy), curproxy->id,
6845 newsrv->id, pname);
6846 cfgerr++;
6847 goto next_srv;
6848 }
6849 } else
6850 px = curproxy;
6851
6852 srv = findserver(px, sname);
6853 if (!srv) {
6854 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6855 proxy_type_str(curproxy), curproxy->id,
6856 newsrv->id, sname);
6857 cfgerr++;
6858 goto next_srv;
6859 }
6860
Willy Tarreau32091232014-05-16 13:52:00 +02006861 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6862 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6863 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006864 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006865 "tracking as it does not have any check nor agent enabled.\n",
6866 proxy_type_str(curproxy), curproxy->id,
6867 newsrv->id, px->id, srv->id);
6868 cfgerr++;
6869 goto next_srv;
6870 }
6871
6872 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6873
6874 if (loop) {
6875 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6876 "belongs to a tracking chain looping back to %s/%s.\n",
6877 proxy_type_str(curproxy), curproxy->id,
6878 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006879 cfgerr++;
6880 goto next_srv;
6881 }
6882
6883 if (curproxy != px &&
6884 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6885 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6886 "tracking: disable-on-404 option inconsistency.\n",
6887 proxy_type_str(curproxy), curproxy->id,
6888 newsrv->id, px->id, srv->id);
6889 cfgerr++;
6890 goto next_srv;
6891 }
6892
6893 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006894 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006895 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006896 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006897 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006898 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006899 }
6900
6901 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006902 newsrv->tracknext = srv->trackers;
6903 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006904
6905 free(newsrv->trackit);
6906 newsrv->trackit = NULL;
6907 }
6908 next_srv:
6909 newsrv = newsrv->next;
6910 }
6911
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006912 /* We have to initialize the server lookup mechanism depending
6913 * on what LB algorithm was choosen.
6914 */
6915
6916 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6917 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6918 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006919 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6920 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6921 init_server_map(curproxy);
6922 } else {
6923 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6924 fwrr_init_server_groups(curproxy);
6925 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006926 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006927
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006928 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006929 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6930 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6931 fwlc_init_server_tree(curproxy);
6932 } else {
6933 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6934 fas_init_server_tree(curproxy);
6935 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006936 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006937
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006938 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006939 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6940 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6941 chash_init_server_tree(curproxy);
6942 } else {
6943 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6944 init_server_map(curproxy);
6945 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006946 break;
6947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006948
6949 if (curproxy->options & PR_O_LOGASAP)
6950 curproxy->to_log &= ~LW_BYTES;
6951
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006952 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006953 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006954 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6955 proxy_type_str(curproxy), curproxy->id);
6956 err_code |= ERR_WARN;
6957 }
6958
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006959 if (curproxy->mode != PR_MODE_HTTP) {
6960 int optnum;
6961
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006962 if (curproxy->uri_auth) {
6963 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6964 proxy_type_str(curproxy), curproxy->id);
6965 err_code |= ERR_WARN;
6966 curproxy->uri_auth = NULL;
6967 }
6968
Willy Tarreau87cf5142011-08-19 22:57:24 +02006969 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006970 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6971 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6972 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006973 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006974 }
6975
6976 if (curproxy->options & PR_O_ORGTO) {
6977 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6978 "originalto", proxy_type_str(curproxy), curproxy->id);
6979 err_code |= ERR_WARN;
6980 curproxy->options &= ~PR_O_ORGTO;
6981 }
6982
6983 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6984 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6985 (curproxy->cap & cfg_opts[optnum].cap) &&
6986 (curproxy->options & cfg_opts[optnum].val)) {
6987 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6988 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6989 err_code |= ERR_WARN;
6990 curproxy->options &= ~cfg_opts[optnum].val;
6991 }
6992 }
6993
6994 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6995 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6996 (curproxy->cap & cfg_opts2[optnum].cap) &&
6997 (curproxy->options2 & cfg_opts2[optnum].val)) {
6998 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6999 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7000 err_code |= ERR_WARN;
7001 curproxy->options2 &= ~cfg_opts2[optnum].val;
7002 }
7003 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007004
Pieter Baauwd551fb52013-05-08 22:49:23 +02007005#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007006 if (curproxy->conn_src.bind_hdr_occ) {
7007 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007008 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007009 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007010 err_code |= ERR_WARN;
7011 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007012#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007013 }
7014
Willy Tarreaubaaee002006-06-26 02:48:02 +02007015 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007016 * ensure that we're not cross-dressing a TCP server into HTTP.
7017 */
7018 newsrv = curproxy->srv;
7019 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007020 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007021 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7022 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007023 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007024 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007025
Willy Tarreau0cec3312011-10-31 13:49:26 +01007026 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7027 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7028 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7029 err_code |= ERR_WARN;
7030 }
7031
Willy Tarreauc93cd162014-05-13 15:54:22 +02007032 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007033 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7034 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7035 err_code |= ERR_WARN;
7036 }
7037
Pieter Baauwd551fb52013-05-08 22:49:23 +02007038#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007039 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7040 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007041 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 +01007042 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007043 err_code |= ERR_WARN;
7044 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007045#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007046 newsrv = newsrv->next;
7047 }
7048
Willy Tarreauc1a21672009-08-16 22:37:44 +02007049 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007050 if (!curproxy->accept)
7051 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007052
Willy Tarreauc1a21672009-08-16 22:37:44 +02007053 if (curproxy->tcp_req.inspect_delay ||
7054 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007055 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007056
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007057 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007058 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007059 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007060 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007061
7062 /* both TCP and HTTP must check switching rules */
7063 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7064 }
7065
7066 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007067 if (curproxy->tcp_req.inspect_delay ||
7068 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7069 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7070
Emeric Brun97679e72010-09-23 17:56:44 +02007071 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7072 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7073
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007074 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007075 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007076 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007077 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007078
7079 /* If the backend does requires RDP cookie persistence, we have to
7080 * enable the corresponding analyser.
7081 */
7082 if (curproxy->options2 & PR_O2_RDPC_PRST)
7083 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7084 }
7085
Emeric Brunc52962f2012-11-15 18:28:02 +01007086#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007087 /* Configure SSL for each bind line.
7088 * Note: if configuration fails at some point, the ->ctx member
7089 * remains NULL so that listeners can later detach.
7090 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007091 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007092 int alloc_ctx;
7093
Emeric Brunc52962f2012-11-15 18:28:02 +01007094 if (!bind_conf->is_ssl) {
7095 if (bind_conf->default_ctx) {
7096 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7097 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7098 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007099 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007100 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007101 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007102 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007103 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007104 cfgerr++;
7105 continue;
7106 }
7107
Emeric Brun8dc60392014-05-09 13:52:00 +02007108 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007109 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007110 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7111 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");
7112 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007113 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007114 cfgerr++;
7115 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007116 }
7117
Emeric Brunfc0421f2012-09-07 17:30:07 +02007118 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007119 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007120 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007121#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007122
Willy Tarreaue6b98942007-10-29 01:09:36 +01007123 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007124 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007125 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007126 if (!listener->luid) {
7127 /* listener ID not set, use automatic numbering with first
7128 * spare entry starting with next_luid.
7129 */
7130 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7131 listener->conf.id.key = listener->luid = next_id;
7132 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007133 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007134 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007135
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007136 /* enable separate counters */
7137 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7138 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007139 if (!listener->name)
7140 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007141 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007142
Willy Tarreaue6b98942007-10-29 01:09:36 +01007143 if (curproxy->options & PR_O_TCP_NOLING)
7144 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007145 if (!listener->maxconn)
7146 listener->maxconn = curproxy->maxconn;
7147 if (!listener->backlog)
7148 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007149 if (!listener->maxaccept)
7150 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7151
7152 /* we want to have an optimal behaviour on single process mode to
7153 * maximize the work at once, but in multi-process we want to keep
7154 * some fairness between processes, so we target half of the max
7155 * number of events to be balanced over all the processes the proxy
7156 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7157 * used to disable the limit.
7158 */
7159 if (listener->maxaccept > 0) {
7160 if (nbproc > 1)
7161 listener->maxaccept = (listener->maxaccept + 1) / 2;
7162 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7163 }
7164
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007165 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007166 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007167 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007168 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007169
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007170 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7171 listener->options |= LI_O_TCP_RULES;
7172
Willy Tarreaude3041d2010-05-31 10:56:17 +02007173 if (curproxy->mon_mask.s_addr)
7174 listener->options |= LI_O_CHK_MONNET;
7175
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007176 /* smart accept mode is automatic in HTTP mode */
7177 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007178 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007179 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7180 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007181 }
7182
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007183 /* Release unused SSL configs */
7184 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7185 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007186 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007187#ifdef USE_OPENSSL
7188 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007189 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007190 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007191 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007192 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007193#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007194 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007195
Willy Tarreau102df612014-05-07 23:56:38 +02007196 if (nbproc > 1) {
7197 if (curproxy->uri_auth) {
7198 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7199 curproxy->id);
7200 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7201 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7202 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007203 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007204 }
Willy Tarreau102df612014-05-07 23:56:38 +02007205 if (curproxy->appsession_name) {
7206 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7207 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007208 }
Willy Tarreau102df612014-05-07 23:56:38 +02007209 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7210 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7211 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007212 }
7213 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007214
7215 /* create the task associated with the proxy */
7216 curproxy->task = task_new();
7217 if (curproxy->task) {
7218 curproxy->task->context = curproxy;
7219 curproxy->task->process = manage_proxy;
7220 /* no need to queue, it will be done automatically if some
7221 * listener gets limited.
7222 */
7223 curproxy->task->expire = TICK_ETERNITY;
7224 } else {
7225 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7226 curproxy->id);
7227 cfgerr++;
7228 }
7229
Willy Tarreaubaaee002006-06-26 02:48:02 +02007230 curproxy = curproxy->next;
7231 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007232
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007233 /* Check multi-process mode compatibility */
Willy Tarreau4e5ed292014-05-13 13:37:54 +02007234 if (global.nbproc > 1 && global.stats_fe) {
Willy Tarreau67c2abc2014-05-09 18:48:46 +02007235 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7236 unsigned long mask;
7237
7238 mask = nbits(global.nbproc);
7239 if (global.stats_fe->bind_proc)
7240 mask &= global.stats_fe->bind_proc;
7241
7242 if (bind_conf->bind_proc)
7243 mask &= bind_conf->bind_proc;
7244
7245 /* stop here if more than one process is used */
7246 if (popcount(mask) > 1)
7247 break;
7248 }
7249 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7250 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 +01007251 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007252 }
7253
7254 /* automatically compute fullconn if not set. We must not do it in the
7255 * loop above because cross-references are not yet fully resolved.
7256 */
7257 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7258 /* If <fullconn> is not set, let's set it to 10% of the sum of
7259 * the possible incoming frontend's maxconns.
7260 */
7261 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7262 struct proxy *fe;
7263 int total = 0;
7264
7265 /* sum up the number of maxconns of frontends which
7266 * reference this backend at least once or which are
7267 * the same one ('listen').
7268 */
7269 for (fe = proxy; fe; fe = fe->next) {
7270 struct switching_rule *rule;
7271 struct hdr_exp *exp;
7272 int found = 0;
7273
7274 if (!(fe->cap & PR_CAP_FE))
7275 continue;
7276
7277 if (fe == curproxy) /* we're on a "listen" instance */
7278 found = 1;
7279
7280 if (fe->defbe.be == curproxy) /* "default_backend" */
7281 found = 1;
7282
7283 /* check if a "use_backend" rule matches */
7284 if (!found) {
7285 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007286 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007287 found = 1;
7288 break;
7289 }
7290 }
7291 }
7292
7293 /* check if a "reqsetbe" rule matches */
7294 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7295 if (exp->action == ACT_SETBE &&
7296 (struct proxy *)exp->replace == curproxy) {
7297 found = 1;
7298 break;
7299 }
7300 }
7301
7302 /* now we've checked all possible ways to reference a backend
7303 * from a frontend.
7304 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007305 if (!found)
7306 continue;
7307 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007308 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007309 /* we have the sum of the maxconns in <total>. We only
7310 * keep 10% of that sum to set the default fullconn, with
7311 * a hard minimum of 1 (to avoid a divide by zero).
7312 */
7313 curproxy->fullconn = (total + 9) / 10;
7314 if (!curproxy->fullconn)
7315 curproxy->fullconn = 1;
7316 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007317 }
7318
Willy Tarreau056f5682010-06-06 15:51:11 +02007319 /* initialize stick-tables on backend capable proxies. This must not
7320 * be done earlier because the data size may be discovered while parsing
7321 * other proxies.
7322 */
Godbach9703e662013-12-11 21:11:41 +08007323 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007324 if (curproxy->state == PR_STSTOPPED)
7325 continue;
7326
Godbach9703e662013-12-11 21:11:41 +08007327 if (!stktable_init(&curproxy->table)) {
7328 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7329 cfgerr++;
7330 }
7331 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007332
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007333 /*
7334 * Recount currently required checks.
7335 */
7336
7337 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7338 int optnum;
7339
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007340 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7341 if (curproxy->options & cfg_opts[optnum].val)
7342 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007343
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007344 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7345 if (curproxy->options2 & cfg_opts2[optnum].val)
7346 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007347 }
7348
Willy Tarreau122541c2011-09-07 21:24:49 +02007349 if (peers) {
7350 struct peers *curpeers = peers, **last;
7351 struct peer *p, *pb;
7352
7353 /* Remove all peers sections which don't have a valid listener.
7354 * This can happen when a peers section is never referenced and
7355 * does not contain a local peer.
7356 */
7357 last = &peers;
7358 while (*last) {
7359 curpeers = *last;
7360 if (curpeers->peers_fe) {
7361 last = &curpeers->next;
7362 continue;
7363 }
7364
7365 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7366 curpeers->id, localpeer);
7367
7368 p = curpeers->remote;
7369 while (p) {
7370 pb = p->next;
7371 free(p->id);
7372 free(p);
7373 p = pb;
7374 }
7375
7376 /* Destroy and unlink this curpeers section.
7377 * Note: curpeers is backed up into *last.
7378 */
7379 free(curpeers->id);
7380 curpeers = curpeers->next;
7381 free(*last);
7382 *last = curpeers;
7383 }
7384 }
7385
Willy Tarreau34eb6712011-10-24 18:15:04 +02007386 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007387 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007388 MEM_F_SHARED);
7389
Willy Tarreaubb925012009-07-23 13:36:36 +02007390 if (cfgerr > 0)
7391 err_code |= ERR_ALERT | ERR_FATAL;
7392 out:
7393 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007394}
7395
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007396/*
7397 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7398 * parsing sessions.
7399 */
7400void cfg_register_keywords(struct cfg_kw_list *kwl)
7401{
7402 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7403}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007404
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007405/*
7406 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7407 */
7408void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7409{
7410 LIST_DEL(&kwl->list);
7411 LIST_INIT(&kwl->list);
7412}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007413
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007414/* this function register new section in the haproxy configuration file.
7415 * <section_name> is the name of this new section and <section_parser>
7416 * is the called parser. If two section declaration have the same name,
7417 * only the first declared is used.
7418 */
7419int cfg_register_section(char *section_name,
7420 int (*section_parser)(const char *, int, char **, int))
7421{
7422 struct cfg_section *cs;
7423
7424 cs = calloc(1, sizeof(*cs));
7425 if (!cs) {
7426 Alert("register section '%s': out of memory.\n", section_name);
7427 return 0;
7428 }
7429
7430 cs->section_name = section_name;
7431 cs->section_parser = section_parser;
7432
7433 LIST_ADDQ(&sections, &cs->list);
7434
7435 return 1;
7436}
7437
Willy Tarreaubaaee002006-06-26 02:48:02 +02007438/*
7439 * Local variables:
7440 * c-indent-level: 8
7441 * c-basic-offset: 8
7442 * End:
7443 */