blob: ec8f3ae1b37e5b96f09fedaa8a9fea13428136fe [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{
315 if (!LIST_ISEMPTY(&proxy->block_cond)) {
316 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
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100597 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.sslcachesize = atol(args[1]);
604 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100605 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
606 unsigned int ssllifetime;
607 const char *res;
608
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
613 }
614
615 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
616 if (res) {
617 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
618 file, linenum, *res, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622
623 global.tune.ssllifetime = ssllifetime;
624 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100625 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.tune.ssl_max_record = atol(args[1]);
632 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200633#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200634 else if (!strcmp(args[0], "tune.bufsize")) {
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.bufsize = atol(args[1]);
641 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
642 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100643 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100644 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200645 }
646 else if (!strcmp(args[0], "tune.maxrewrite")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.maxrewrite = atol(args[1]);
653 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
654 global.tune.maxrewrite = global.tune.bufsize / 2;
655 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100656 else if (!strcmp(args[0], "tune.idletimer")) {
657 unsigned int idle;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
667 if (res) {
668 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
669 file, linenum, *res, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673
674 if (idle > 65535) {
675 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.idle_timer = idle;
680 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100681 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
682 if (global.tune.client_rcvbuf != 0) {
683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT;
685 goto out;
686 }
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.client_rcvbuf = atol(args[1]);
693 }
694 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
695 if (global.tune.server_rcvbuf != 0) {
696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT;
698 goto out;
699 }
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.server_rcvbuf = atol(args[1]);
706 }
707 else if (!strcmp(args[0], "tune.sndbuf.client")) {
708 if (global.tune.client_sndbuf != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.client_sndbuf = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "tune.sndbuf.server")) {
721 if (global.tune.server_sndbuf != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT;
724 goto out;
725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.server_sndbuf = atol(args[1]);
732 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200733 else if (!strcmp(args[0], "tune.pipesize")) {
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 global.tune.pipesize = atol(args[1]);
740 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100741 else if (!strcmp(args[0], "tune.http.cookielen")) {
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.cookie_len = atol(args[1]) + 1;
748 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200749 else if (!strcmp(args[0], "tune.http.maxhdr")) {
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.max_http_hdr = atol(args[1]);
756 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100757 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
758#ifdef USE_ZLIB
759 if (*args[1]) {
760 global.tune.zlibmemlevel = atoi(args[1]);
761 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
762 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
763 file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 } else {
768 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
769 file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773#else
774 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777#endif
778 }
779 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
780#ifdef USE_ZLIB
781 if (*args[1]) {
782 global.tune.zlibwindowsize = atoi(args[1]);
783 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\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' expects a numeric value between 8 and 15\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795#else
796 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799#endif
800 }
William Lallemandf3747832012-11-09 12:33:10 +0100801 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
802 if (*args[1]) {
803 global.tune.comp_maxlevel = atoi(args[1]);
804 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
805 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
806 file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 } else {
811 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
812 file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 else if (!strcmp(args[0], "uid")) {
818 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200819 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 global.uid = atol(args[1]);
829 }
830 else if (!strcmp(args[0], "gid")) {
831 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT;
834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 global.gid = atol(args[1]);
842 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200843 /* user/group name handling */
844 else if (!strcmp(args[0], "user")) {
845 struct passwd *ha_user;
846 if (global.uid != 0) {
847 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT;
849 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200850 }
851 errno = 0;
852 ha_user = getpwnam(args[1]);
853 if (ha_user != NULL) {
854 global.uid = (int)ha_user->pw_uid;
855 }
856 else {
857 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 +0200858 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 }
860 }
861 else if (!strcmp(args[0], "group")) {
862 struct group *ha_group;
863 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200864 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200865 err_code |= ERR_ALERT;
866 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200867 }
868 errno = 0;
869 ha_group = getgrnam(args[1]);
870 if (ha_group != NULL) {
871 global.gid = (int)ha_group->gr_gid;
872 }
873 else {
874 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 +0200875 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200876 }
877 }
878 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
885 global.nbproc = atol(args[1]);
886 }
887 else if (!strcmp(args[0], "maxconn")) {
888 if (global.maxconn != 0) {
889 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 global.maxconn = atol(args[1]);
899#ifdef SYSTEM_MAXCONN
900 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
901 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);
902 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905#endif /* SYSTEM_MAXCONN */
906 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200907 else if (!strcmp(args[0], "maxsslconn")) {
908#ifdef USE_OPENSSL
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.maxsslconn = atol(args[1]);
915#else
Emeric Brun0914df82012-10-02 18:45:42 +0200916 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200919#endif
920 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100921 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
922#ifdef USE_OPENSSL
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 free(global.listen_default_ciphers);
929 global.listen_default_ciphers = strdup(args[1]);
930#else
931 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934#endif
935 }
936 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
937#ifdef USE_OPENSSL
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 free(global.connect_default_ciphers);
944 global.connect_default_ciphers = strdup(args[1]);
945#else
946 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949#endif
950 }
Emeric Brun850efd52014-01-29 12:24:34 +0100951 else if (!strcmp(args[0], "ssl-server-verify")) {
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 if (strcmp(args[1],"none") == 0)
958 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
959 else if (strcmp(args[1],"required") == 0)
960 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
961 else {
962 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200967 else if (!strcmp(args[0], "maxconnrate")) {
968 if (global.cps_lim != 0) {
969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
970 err_code |= ERR_ALERT;
971 goto out;
972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 global.cps_lim = atol(args[1]);
979 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200980 else if (!strcmp(args[0], "maxsessrate")) {
981 if (global.sps_lim != 0) {
982 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT;
984 goto out;
985 }
986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991 global.sps_lim = atol(args[1]);
992 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200993 else if (!strcmp(args[0], "maxsslrate")) {
994 if (global.ssl_lim != 0) {
995 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT;
997 goto out;
998 }
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 global.ssl_lim = atol(args[1]);
1005 }
William Lallemandd85f9172012-11-09 17:05:39 +01001006 else if (!strcmp(args[0], "maxcomprate")) {
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.comp_rate_lim = atoi(args[1]) * 1024;
1013 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001014 else if (!strcmp(args[0], "maxpipes")) {
1015 if (global.maxpipes != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001024 }
1025 global.maxpipes = atol(args[1]);
1026 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001027 else if (!strcmp(args[0], "maxzlibmem")) {
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
William Lallemande3a7d992012-11-20 11:25:20 +01001033 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001034 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001035 else if (!strcmp(args[0], "maxcompcpuusage")) {
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001042 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001043 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047}
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 else if (!strcmp(args[0], "ulimit-n")) {
1050 if (global.rlimit_nofile != 0) {
1051 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 global.rlimit_nofile = atol(args[1]);
1061 }
1062 else if (!strcmp(args[0], "chroot")) {
1063 if (global.chroot != NULL) {
1064 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001065 err_code |= ERR_ALERT;
1066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 }
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 global.chroot = strdup(args[1]);
1074 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001075 else if (!strcmp(args[0], "description")) {
1076 int i, len=0;
1077 char *d;
1078
1079 if (!*args[1]) {
1080 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1081 file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085
Willy Tarreau348acfe2014-04-14 15:00:39 +02001086 for (i = 1; *args[i]; i++)
1087 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001088
1089 if (global.desc)
1090 free(global.desc);
1091
1092 global.desc = d = (char *)calloc(1, len);
1093
Willy Tarreau348acfe2014-04-14 15:00:39 +02001094 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1095 for (i = 2; *args[i]; i++)
1096 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 }
1098 else if (!strcmp(args[0], "node")) {
1099 int i;
1100 char c;
1101
1102 for (i=0; args[1][i]; i++) {
1103 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001104 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1105 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001106 break;
1107 }
1108
1109 if (!i || args[1][i]) {
1110 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1111 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1112 file, linenum, args[0]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116
1117 if (global.node)
1118 free(global.node);
1119
1120 global.node = strdup(args[1]);
1121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "pidfile")) {
1123 if (global.pidfile != NULL) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.pidfile = strdup(args[1]);
1134 }
Emeric Bruned760922010-10-22 17:59:25 +02001135 else if (!strcmp(args[0], "unix-bind")) {
1136 int cur_arg = 1;
1137 while (*(args[cur_arg])) {
1138 if (!strcmp(args[cur_arg], "prefix")) {
1139 if (global.unix_bind.prefix != NULL) {
1140 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1141 err_code |= ERR_ALERT;
1142 cur_arg += 2;
1143 continue;
1144 }
1145
1146 if (*(args[cur_arg+1]) == 0) {
1147 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1152 cur_arg += 2;
1153 continue;
1154 }
1155
1156 if (!strcmp(args[cur_arg], "mode")) {
1157
1158 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1159 cur_arg += 2;
1160 continue;
1161 }
1162
1163 if (!strcmp(args[cur_arg], "uid")) {
1164
1165 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1166 cur_arg += 2;
1167 continue;
1168 }
1169
1170 if (!strcmp(args[cur_arg], "gid")) {
1171
1172 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1173 cur_arg += 2;
1174 continue;
1175 }
1176
1177 if (!strcmp(args[cur_arg], "user")) {
1178 struct passwd *user;
1179
1180 user = getpwnam(args[cur_arg + 1]);
1181 if (!user) {
1182 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1183 file, linenum, args[0], args[cur_arg + 1 ]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 global.unix_bind.ux.uid = user->pw_uid;
1189 cur_arg += 2;
1190 continue;
1191 }
1192
1193 if (!strcmp(args[cur_arg], "group")) {
1194 struct group *group;
1195
1196 group = getgrnam(args[cur_arg + 1]);
1197 if (!group) {
1198 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1199 file, linenum, args[0], args[cur_arg + 1 ]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203
1204 global.unix_bind.ux.gid = group->gr_gid;
1205 cur_arg += 2;
1206 continue;
1207 }
1208
Willy Tarreaub48f9582011-09-05 01:17:06 +02001209 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214 }
William Lallemand0f99e342011-10-12 17:50:54 +02001215 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1216 /* delete previous herited or defined syslog servers */
1217 struct logsrv *back;
1218 struct logsrv *tmp;
1219
1220 if (*(args[1]) != 0) {
1221 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1227 LIST_DEL(&tmp->list);
1228 free(tmp);
1229 }
1230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001232 struct sockaddr_storage *sk;
1233 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001234 struct logsrv *logsrv;
1235
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 if (*(args[1]) == 0 || *(args[2]) == 0) {
1237 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 }
William Lallemand0f99e342011-10-12 17:50:54 +02001241
1242 logsrv = calloc(1, sizeof(struct logsrv));
1243
1244 logsrv->facility = get_log_facility(args[2]);
1245 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001247 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001248 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 }
1250
William Lallemand0f99e342011-10-12 17:50:54 +02001251 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001253 logsrv->level = get_log_level(args[3]);
1254 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001257 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 }
1260
William Lallemand0f99e342011-10-12 17:50:54 +02001261 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001262 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001263 logsrv->minlvl = get_log_level(args[4]);
1264 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001265 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001267 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001268 }
1269 }
1270
Willy Tarreau902636f2013-03-10 19:44:48 +01001271 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001272 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001273 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001275 free(logsrv);
1276 goto out;
1277 }
1278 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001279
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001280 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001281 if (port1 != port2) {
1282 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1283 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001284 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001285 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001286 goto out;
1287 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001288
William Lallemand0f99e342011-10-12 17:50:54 +02001289 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001290 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001291 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293
William Lallemand0f99e342011-10-12 17:50:54 +02001294 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001295 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001296 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1297 char *name;
1298 int len;
1299
1300 if (global.log_send_hostname != NULL) {
1301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT;
1303 goto out;
1304 }
1305
1306 if (*(args[1]))
1307 name = args[1];
1308 else
1309 name = hostname;
1310
1311 len = strlen(name);
1312
1313 /* We'll add a space after the name to respect the log format */
1314 free(global.log_send_hostname);
1315 global.log_send_hostname = malloc(len + 2);
1316 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1317 }
Kevinm48936af2010-12-22 16:08:21 +00001318 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 free(global.log_tag);
1325 global.log_tag = strdup(args[1]);
1326 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001327 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1328 if (global.spread_checks != 0) {
1329 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001330 err_code |= ERR_ALERT;
1331 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001332 }
1333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001337 }
1338 global.spread_checks = atol(args[1]);
1339 if (global.spread_checks < 0 || global.spread_checks > 50) {
1340 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001344 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1345 const char *err;
1346 unsigned int val;
1347
1348
1349 if (*(args[1]) == 0) {
1350 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354
1355 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1356 if (err) {
1357 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1358 err_code |= ERR_ALERT | ERR_FATAL;
1359 }
1360 global.max_spread_checks = val;
1361 if (global.max_spread_checks < 0) {
1362 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 }
1365 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001366 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1367#ifdef USE_CPU_AFFINITY
1368 int cur_arg, i;
1369 unsigned int proc = 0;
1370 unsigned long cpus = 0;
1371
1372 if (strcmp(args[1], "all") == 0)
1373 proc = 0xFFFFFFFF;
1374 else if (strcmp(args[1], "odd") == 0)
1375 proc = 0x55555555;
1376 else if (strcmp(args[1], "even") == 0)
1377 proc = 0xAAAAAAAA;
1378 else {
1379 proc = atoi(args[1]);
1380 if (proc >= 1 && proc <= 32)
1381 proc = 1 << (proc - 1);
1382 }
1383
1384 if (!proc || !*args[2]) {
1385 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1386 file, linenum, args[0]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390
1391 cur_arg = 2;
1392 while (*args[cur_arg]) {
1393 unsigned int low, high;
1394
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001395 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 char *dash = strchr(args[cur_arg], '-');
1397
1398 low = high = str2uic(args[cur_arg]);
1399 if (dash)
1400 high = str2uic(dash + 1);
1401
1402 if (high < low) {
1403 unsigned int swap = low;
1404 low = high;
1405 high = swap;
1406 }
1407
1408 if (low < 0 || high >= sizeof(long) * 8) {
1409 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1410 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
1415 while (low <= high)
1416 cpus |= 1UL << low++;
1417 }
1418 else {
1419 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1420 file, linenum, args[0], args[cur_arg]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424 cur_arg++;
1425 }
1426 for (i = 0; i < 32; i++)
1427 if (proc & (1 << i))
1428 global.cpu_map[i] = cpus;
1429#else
1430 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433#endif
1434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001436 struct cfg_kw_list *kwl;
1437 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001438 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001439
1440 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1441 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1442 if (kwl->kw[index].section != CFG_GLOBAL)
1443 continue;
1444 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001445 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001446 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001447 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001449 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001450 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001451 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_WARN;
1453 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001454 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001456 }
1457 }
1458 }
1459
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001463
Willy Tarreau058e9072009-07-20 09:30:05 +02001464 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001465 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467}
1468
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001469void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001471 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 defproxy.mode = PR_MODE_TCP;
1473 defproxy.state = PR_STNEW;
1474 defproxy.maxconn = cfg_maxpconn;
1475 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001476
Simon Horman66183002013-02-23 10:16:43 +09001477 defproxy.defsrv.check.inter = DEF_CHKINTR;
1478 defproxy.defsrv.check.fastinter = 0;
1479 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001480 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1481 defproxy.defsrv.agent.fastinter = 0;
1482 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001483 defproxy.defsrv.check.rise = DEF_RISETIME;
1484 defproxy.defsrv.check.fall = DEF_FALLTIME;
1485 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1486 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001487 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001488 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001489 defproxy.defsrv.maxqueue = 0;
1490 defproxy.defsrv.minconn = 0;
1491 defproxy.defsrv.maxconn = 0;
1492 defproxy.defsrv.slowstart = 0;
1493 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1494 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1495 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496}
1497
Willy Tarreauade5ec42010-01-28 19:33:49 +01001498
1499static int create_cond_regex_rule(const char *file, int line,
1500 struct proxy *px, int dir, int action, int flags,
1501 const char *cmd, const char *reg, const char *repl,
1502 const char **cond_start)
1503{
1504 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001505 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001506 const char *err;
1507 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001508 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001509
1510 if (px == &defproxy) {
1511 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto err;
1514 }
1515
1516 if (*reg == 0) {
1517 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto err;
1520 }
1521
1522 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1523 err_code |= ERR_WARN;
1524
Willy Tarreau5321c422010-01-28 20:35:13 +01001525 if (cond_start &&
1526 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001527 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1528 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1529 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto err;
1532 }
1533 }
1534 else if (cond_start && **cond_start) {
1535 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1536 file, line, cmd, *cond_start);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto err;
1539 }
1540
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001541 err_code |= warnif_cond_conflicts(cond,
1542 (dir == SMP_OPT_DIR_REQ) ?
1543 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1544 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1545 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001546
Willy Tarreauade5ec42010-01-28 19:33:49 +01001547 preg = calloc(1, sizeof(regex_t));
1548 if (!preg) {
1549 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1550 err_code = ERR_ALERT | ERR_FATAL;
1551 goto err;
1552 }
1553
1554 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1555 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1556 err_code = ERR_ALERT | ERR_FATAL;
1557 goto err;
1558 }
1559
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001560 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001561 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001562 if (repl && err) {
1563 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1564 file, line, cmd, *err);
1565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto err;
1567 }
1568
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001569 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001570 err_code |= ERR_WARN;
1571
Willy Tarreauf4068b62012-05-08 17:37:49 +02001572 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001573 return err_code;
1574 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001575 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001576 free(preg);
1577 return err_code;
1578}
1579
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001581 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001582 * Returns the error code, 0 if OK, or any combination of :
1583 * - ERR_ABORT: must abort ASAP
1584 * - ERR_FATAL: we can continue parsing but not start the service
1585 * - ERR_WARN: a warning has been emitted
1586 * - ERR_ALERT: an alert has been emitted
1587 * Only the two first ones can stop processing, the two others are just
1588 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001590int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1591{
1592 static struct peers *curpeers = NULL;
1593 struct peer *newpeer = NULL;
1594 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001595 struct bind_conf *bind_conf;
1596 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001597 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001598 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001599
1600 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001601 if (!*args[1]) {
1602 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001603 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001604 goto out;
1605 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001606
1607 err = invalid_char(args[1]);
1608 if (err) {
1609 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1610 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001611 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001612 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001613 }
1614
1615 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1616 /*
1617 * If there are two proxies with the same name only following
1618 * combinations are allowed:
1619 */
1620 if (strcmp(curpeers->id, args[1]) == 0) {
1621 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1622 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1623 err_code |= ERR_WARN;
1624 }
1625 }
1626
1627 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1628 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1629 err_code |= ERR_ALERT | ERR_ABORT;
1630 goto out;
1631 }
1632
1633 curpeers->next = peers;
1634 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001635 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001636 curpeers->conf.line = linenum;
1637 curpeers->last_change = now.tv_sec;
1638 curpeers->id = strdup(args[1]);
1639 }
1640 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001641 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001643 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001644
1645 if (!*args[2]) {
1646 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1647 file, linenum, args[0]);
1648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
1650 }
1651
1652 err = invalid_char(args[1]);
1653 if (err) {
1654 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1655 file, linenum, *err, args[1]);
1656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
1658 }
1659
1660 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
1664 }
1665
1666 /* the peers are linked backwards first */
1667 curpeers->count++;
1668 newpeer->next = curpeers->remote;
1669 curpeers->remote = newpeer;
1670 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001671 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 newpeer->conf.line = linenum;
1673
1674 newpeer->last_change = now.tv_sec;
1675 newpeer->id = strdup(args[1]);
1676
Willy Tarreau902636f2013-03-10 19:44:48 +01001677 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001678 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001679 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001682 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001683
1684 proto = protocol_by_family(sk->ss_family);
1685 if (!proto || !proto->connect) {
1686 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1687 file, linenum, args[0], args[1]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001691
1692 if (port1 != port2) {
1693 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1694 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
Willy Tarreau2aa38802013-02-20 19:20:59 +01001699 if (!port1) {
1700 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1701 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
1704 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001705
Emeric Brun32da3c42010-09-23 18:39:19 +02001706 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001707 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001708 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001709 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001710
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 if (strcmp(newpeer->id, localpeer) == 0) {
1712 /* Current is local peer, it define a frontend */
1713 newpeer->local = 1;
1714
1715 if (!curpeers->peers_fe) {
1716 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1717 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1718 err_code |= ERR_ALERT | ERR_ABORT;
1719 goto out;
1720 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001721
Willy Tarreau237250c2011-07-29 01:49:03 +02001722 init_new_proxy(curpeers->peers_fe);
1723 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001724
1725 curpeers->peers_fe->last_change = now.tv_sec;
1726 curpeers->peers_fe->id = strdup(args[1]);
1727 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001728 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001729 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1730 curpeers->peers_fe->timeout.connect = 5000;
1731 curpeers->peers_fe->accept = peer_accept;
1732 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001733 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1734 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001735
1736 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1737
Willy Tarreau902636f2013-03-10 19:44:48 +01001738 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1739 if (errmsg && *errmsg) {
1740 indent_msg(&errmsg, 2);
1741 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001742 }
1743 else
1744 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1745 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001746 err_code |= ERR_FATAL;
1747 goto out;
1748 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001749
1750 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1751 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1752 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1753 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1754 l->accept = session_accept;
1755 l->handler = process_session;
1756 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1757 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1758 global.maxsock += l->maxconn;
1759 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001760 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001761 else {
1762 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1763 file, linenum, args[0], args[1],
1764 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1765 err_code |= ERR_FATAL;
1766 goto out;
1767 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001768 }
1769 } /* neither "peer" nor "peers" */
1770 else if (*args[0] != 0) {
1771 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775
1776out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001777 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001778 return err_code;
1779}
1780
Willy Tarreau3842f002009-06-14 11:39:52 +02001781int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782{
1783 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001784 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001785 int rc;
1786 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001787 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001788 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001789 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001790 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001791 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if (!strcmp(args[0], "listen"))
1794 rc = PR_CAP_LISTEN;
1795 else if (!strcmp(args[0], "frontend"))
1796 rc = PR_CAP_FE | PR_CAP_RS;
1797 else if (!strcmp(args[0], "backend"))
1798 rc = PR_CAP_BE | PR_CAP_RS;
1799 else if (!strcmp(args[0], "ruleset"))
1800 rc = PR_CAP_RS;
1801 else
1802 rc = PR_CAP_NONE;
1803
1804 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001805 struct ebpt_node *node;
1806
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 if (!*args[1]) {
1808 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1809 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1810 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_ALERT | ERR_ABORT;
1812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001814
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001815 err = invalid_char(args[1]);
1816 if (err) {
1817 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1818 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001820 }
1821
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001822 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1823 curproxy = container_of(node, struct proxy, conf.by_name);
1824
1825 if (strcmp(curproxy->id, args[1]) != 0)
1826 break;
1827
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001828 /*
1829 * If there are two proxies with the same name only following
1830 * combinations are allowed:
1831 *
1832 * listen backend frontend ruleset
1833 * listen - - - -
1834 * backend - - OK -
1835 * frontend - OK - -
1836 * ruleset - - - -
1837 */
1838
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001839 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1840 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001841 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1842 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1843 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001845 }
1846 }
1847
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1849 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001850 err_code |= ERR_ALERT | ERR_ABORT;
1851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001853
Willy Tarreau97cb7802010-01-03 20:23:58 +01001854 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 curproxy->next = proxy;
1856 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001857 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1858 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001859 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001862 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863
1864 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001866 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001867
Willy Tarreau4348fad2012-09-20 16:48:07 +02001868 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1869
Willy Tarreau902636f2013-03-10 19:44:48 +01001870 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1871 if (errmsg && *errmsg) {
1872 indent_msg(&errmsg, 2);
1873 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001874 }
1875 else
1876 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1877 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_FATAL;
1879 goto out;
1880 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001881
Willy Tarreau4348fad2012-09-20 16:48:07 +02001882 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001883 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 }
1886
1887 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001888 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001889 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001890
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001893 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001894 curproxy->no_options = defproxy.no_options;
1895 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001896 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001897 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001898 curproxy->except_net = defproxy.except_net;
1899 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001900 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001901 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001903 if (defproxy.fwdfor_hdr_len) {
1904 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1905 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1906 }
1907
Willy Tarreaub86db342009-11-30 11:50:16 +01001908 if (defproxy.orgto_hdr_len) {
1909 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1910 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1911 }
1912
Mark Lamourinec2247f02012-01-04 13:02:01 -05001913 if (defproxy.server_id_hdr_len) {
1914 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1915 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1916 }
1917
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (curproxy->cap & PR_CAP_FE) {
1919 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001920 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001921 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
1923 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001924 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1925 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926
1927 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929
Willy Tarreau977b8e42006-12-29 14:19:17 +01001930 if (curproxy->cap & PR_CAP_BE) {
1931 curproxy->fullconn = defproxy.fullconn;
1932 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001934 if (defproxy.check_req) {
1935 curproxy->check_req = calloc(1, defproxy.check_len);
1936 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001938 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001940 if (defproxy.expect_str) {
1941 curproxy->expect_str = strdup(defproxy.expect_str);
1942 if (defproxy.expect_regex) {
1943 /* note: this regex is known to be valid */
1944 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1945 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1946 }
1947 }
1948
Willy Tarreau67402132012-05-31 20:40:20 +02001949 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001950 if (defproxy.cookie_name)
1951 curproxy->cookie_name = strdup(defproxy.cookie_name);
1952 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001953 if (defproxy.cookie_domain)
1954 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001955
Willy Tarreau31936852010-10-06 16:59:56 +02001956 if (defproxy.cookie_maxidle)
1957 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1958
1959 if (defproxy.cookie_maxlife)
1960 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1961
Emeric Brun647caf12009-06-30 17:57:00 +02001962 if (defproxy.rdp_cookie_name)
1963 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1964 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1965
Willy Tarreau01732802007-11-01 22:48:15 +01001966 if (defproxy.url_param_name)
1967 curproxy->url_param_name = strdup(defproxy.url_param_name);
1968 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001969
Benoitaffb4812009-03-25 13:02:10 +01001970 if (defproxy.hh_name)
1971 curproxy->hh_name = strdup(defproxy.hh_name);
1972 curproxy->hh_len = defproxy.hh_len;
1973 curproxy->hh_match_domain = defproxy.hh_match_domain;
1974
Willy Tarreauef9a3602012-12-08 22:29:20 +01001975 if (defproxy.conn_src.iface_name)
1976 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1977 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001978 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001979#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001980 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001981#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001984 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001985 if (defproxy.capture_name)
1986 curproxy->capture_name = strdup(defproxy.capture_name);
1987 curproxy->capture_namelen = defproxy.capture_namelen;
1988 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990
Willy Tarreau977b8e42006-12-29 14:19:17 +01001991 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001992 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001993 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001994 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001995 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996 curproxy->mon_net = defproxy.mon_net;
1997 curproxy->mon_mask = defproxy.mon_mask;
1998 if (defproxy.monitor_uri)
1999 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2000 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002001 if (defproxy.defbe.name)
2002 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002003
2004 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002005 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2006 if (curproxy->conf.logformat_string &&
2007 curproxy->conf.logformat_string != default_http_log_format &&
2008 curproxy->conf.logformat_string != default_tcp_log_format &&
2009 curproxy->conf.logformat_string != clf_http_log_format)
2010 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2011
2012 if (defproxy.conf.lfs_file) {
2013 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2014 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2015 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002016 }
2017
2018 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002019 curproxy->timeout.connect = defproxy.timeout.connect;
2020 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002021 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002022 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002023 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002024 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002025 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002026 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002027 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002028 }
2029
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002031 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002032
2033 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002034 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002035 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002036 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002037 LIST_INIT(&node->list);
2038 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2039 }
2040
Willy Tarreau62a61232013-04-12 18:13:46 +02002041 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2042 if (curproxy->conf.uniqueid_format_string)
2043 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2044
2045 if (defproxy.conf.uif_file) {
2046 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2047 curproxy->conf.uif_line = defproxy.conf.uif_line;
2048 }
William Lallemanda73203e2012-03-12 12:48:57 +01002049
2050 /* copy default header unique id */
2051 if (defproxy.header_unique_id)
2052 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2053
William Lallemand82fe75c2012-10-23 10:25:10 +02002054 /* default compression options */
2055 if (defproxy.comp != NULL) {
2056 curproxy->comp = calloc(1, sizeof(struct comp));
2057 curproxy->comp->algos = defproxy.comp->algos;
2058 curproxy->comp->types = defproxy.comp->types;
2059 }
2060
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002062 curproxy->conf.used_listener_id = EB_ROOT;
2063 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002064
Willy Tarreau93893792009-07-23 13:19:11 +02002065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 }
2067 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2068 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002069 /* FIXME-20070101: we should do this too at the end of the
2070 * config parsing to free all default values.
2071 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002072 free(defproxy.check_req);
2073 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002074 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002075 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002076 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002077 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002078 free(defproxy.capture_name);
2079 free(defproxy.monitor_uri);
2080 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002081 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002082 free(defproxy.fwdfor_hdr_name);
2083 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002084 free(defproxy.orgto_hdr_name);
2085 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002086 free(defproxy.server_id_hdr_name);
2087 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002088 free(defproxy.expect_str);
2089 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002090
Willy Tarreau62a61232013-04-12 18:13:46 +02002091 if (defproxy.conf.logformat_string != default_http_log_format &&
2092 defproxy.conf.logformat_string != default_tcp_log_format &&
2093 defproxy.conf.logformat_string != clf_http_log_format)
2094 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002095
Willy Tarreau62a61232013-04-12 18:13:46 +02002096 free(defproxy.conf.uniqueid_format_string);
2097 free(defproxy.conf.lfs_file);
2098 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002099
Willy Tarreaua534fea2008-08-03 12:19:50 +02002100 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002101 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002102
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 /* we cannot free uri_auth because it might already be used */
2104 init_default_instance();
2105 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002106 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2107 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 }
2111 else if (curproxy == NULL) {
2112 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002116
2117 /* update the current file and line being parsed */
2118 curproxy->conf.args.file = curproxy->conf.file;
2119 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120
2121 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002122 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2123 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2124 if (err_code & ERR_FATAL)
2125 goto out;
2126 }
2127 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002128 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002129 int cur_arg;
2130
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 if (curproxy == &defproxy) {
2132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002136 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138
Willy Tarreau24709282013-03-10 21:32:12 +01002139 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002140 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002145
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002146 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002147
2148 /* use default settings for unix sockets */
2149 bind_conf->ux.uid = global.unix_bind.ux.uid;
2150 bind_conf->ux.gid = global.unix_bind.ux.gid;
2151 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002152
2153 /* NOTE: the following line might create several listeners if there
2154 * are comma-separated IPs or port ranges. So all further processing
2155 * will have to be applied to all listeners created after last_listen.
2156 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002157 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2158 if (errmsg && *errmsg) {
2159 indent_msg(&errmsg, 2);
2160 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002161 }
2162 else
2163 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2164 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002168
Willy Tarreau4348fad2012-09-20 16:48:07 +02002169 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2170 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002171 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002172 }
2173
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002174 cur_arg = 2;
2175 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002176 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002177 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002178 char *err;
2179
Willy Tarreau26982662012-09-12 23:17:10 +02002180 kw = bind_find_kw(args[cur_arg]);
2181 if (kw) {
2182 char *err = NULL;
2183 int code;
2184
2185 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002186 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2187 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002188 cur_arg += 1 + kw->skip ;
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
Willy Tarreau4348fad2012-09-20 16:48:07 +02002193 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002194 err_code |= code;
2195
2196 if (code) {
2197 if (err && *err) {
2198 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002199 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002200 }
2201 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002202 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2203 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002204 if (code & ERR_FATAL) {
2205 free(err);
2206 cur_arg += 1 + kw->skip;
2207 goto out;
2208 }
2209 }
2210 free(err);
2211 cur_arg += 1 + kw->skip;
2212 continue;
2213 }
2214
Willy Tarreau8638f482012-09-18 18:01:17 +02002215 err = NULL;
2216 if (!bind_dumped) {
2217 bind_dump_kws(&err);
2218 indent_msg(&err, 4);
2219 bind_dumped = 1;
2220 }
2221
2222 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2223 file, linenum, args[0], args[1], args[cur_arg],
2224 err ? " Registered keywords :" : "", err ? err : "");
2225 free(err);
2226
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002229 }
Willy Tarreau93893792009-07-23 13:19:11 +02002230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
2232 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002233 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 /* flush useless bits */
2243 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002246 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002247 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002249
Willy Tarreau1c47f852006-07-09 08:22:27 +02002250 if (!*args[1]) {
2251 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002255 }
2256
Willy Tarreaua534fea2008-08-03 12:19:50 +02002257 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002258 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002259 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002260 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002261 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2262
Willy Tarreau93893792009-07-23 13:19:11 +02002263 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2266 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2267 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2268 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2269 else {
2270 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 }
2274 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002275 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002276 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002277
2278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002283 }
2284
2285 if (!*args[1]) {
2286 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2287 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002290 }
2291
2292 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002293 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002294
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002295 if (curproxy->uuid <= 0) {
2296 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002297 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002300 }
2301
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002302 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2303 if (node) {
2304 struct proxy *target = container_of(node, struct proxy, conf.id);
2305 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2306 file, linenum, proxy_type_str(curproxy), curproxy->id,
2307 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002312 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002313 else if (!strcmp(args[0], "description")) {
2314 int i, len=0;
2315 char *d;
2316
Cyril Bonté99ed3272010-01-24 23:29:44 +01002317 if (curproxy == &defproxy) {
2318 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2319 file, linenum, args[0]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002324 if (!*args[1]) {
2325 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2326 file, linenum, args[0]);
2327 return -1;
2328 }
2329
Willy Tarreau348acfe2014-04-14 15:00:39 +02002330 for (i = 1; *args[i]; i++)
2331 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002332
2333 d = (char *)calloc(1, len);
2334 curproxy->desc = d;
2335
Willy Tarreau348acfe2014-04-14 15:00:39 +02002336 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2337 for (i = 2; *args[i]; i++)
2338 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002339
2340 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2342 curproxy->state = PR_STSTOPPED;
2343 }
2344 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2345 curproxy->state = PR_STNEW;
2346 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002347 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2348 int cur_arg = 1;
2349 unsigned int set = 0;
2350
2351 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002352 unsigned int low, high;
2353
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002354 if (strcmp(args[cur_arg], "all") == 0) {
2355 set = 0;
2356 break;
2357 }
2358 else if (strcmp(args[cur_arg], "odd") == 0) {
2359 set |= 0x55555555;
2360 }
2361 else if (strcmp(args[cur_arg], "even") == 0) {
2362 set |= 0xAAAAAAAA;
2363 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002364 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002365 char *dash = strchr(args[cur_arg], '-');
2366
2367 low = high = str2uic(args[cur_arg]);
2368 if (dash)
2369 high = str2uic(dash + 1);
2370
2371 if (high < low) {
2372 unsigned int swap = low;
2373 low = high;
2374 high = swap;
2375 }
2376
2377 if (low < 1 || high > 32) {
2378 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002382 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002383
2384 if (high > global.nbproc) {
2385 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2386 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002388 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002389 while (low <= high)
2390 set |= 1 << (low++ - 1);
2391 }
2392 else {
2393 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2394 file, linenum, args[0]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002397 }
2398 cur_arg++;
2399 }
2400 curproxy->bind_proc = set;
2401 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002402 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002403 if (curproxy == &defproxy) {
2404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002407 }
2408
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002409 err = invalid_char(args[1]);
2410 if (err) {
2411 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2412 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002414 }
2415
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002416 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002417 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2418 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002421 }
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2424 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002428
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 if (*(args[1]) == 0) {
2430 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2431 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002435
Willy Tarreau67402132012-05-31 20:40:20 +02002436 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002437 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002438 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002439 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 curproxy->cookie_name = strdup(args[1]);
2441 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002442
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 cur_arg = 2;
2444 while (*(args[cur_arg])) {
2445 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002446 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }
2448 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002449 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002452 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002455 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 }
2457 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002458 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002460 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002461 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002464 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002466 else if (!strcmp(args[cur_arg], "httponly")) {
2467 curproxy->ck_opts |= PR_CK_HTTPONLY;
2468 }
2469 else if (!strcmp(args[cur_arg], "secure")) {
2470 curproxy->ck_opts |= PR_CK_SECURE;
2471 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002472 else if (!strcmp(args[cur_arg], "domain")) {
2473 if (!*args[cur_arg + 1]) {
2474 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2475 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002478 }
2479
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002480 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002481 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002482 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2483 " dots nor does not start with a dot."
2484 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002485 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002486 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002487 }
2488
2489 err = invalid_domainchar(args[cur_arg + 1]);
2490 if (err) {
2491 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2492 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002495 }
2496
Willy Tarreau68a897b2009-12-03 23:28:34 +01002497 if (!curproxy->cookie_domain) {
2498 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2499 } else {
2500 /* one domain was already specified, add another one by
2501 * building the string which will be returned along with
2502 * the cookie.
2503 */
2504 char *new_ptr;
2505 int new_len = strlen(curproxy->cookie_domain) +
2506 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2507 new_ptr = malloc(new_len);
2508 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2509 free(curproxy->cookie_domain);
2510 curproxy->cookie_domain = new_ptr;
2511 }
Willy Tarreau31936852010-10-06 16:59:56 +02002512 cur_arg++;
2513 }
2514 else if (!strcmp(args[cur_arg], "maxidle")) {
2515 unsigned int maxidle;
2516 const char *res;
2517
2518 if (!*args[cur_arg + 1]) {
2519 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2520 file, linenum, args[cur_arg]);
2521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
2523 }
2524
2525 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2526 if (res) {
2527 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2528 file, linenum, *res, args[cur_arg]);
2529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
2531 }
2532 curproxy->cookie_maxidle = maxidle;
2533 cur_arg++;
2534 }
2535 else if (!strcmp(args[cur_arg], "maxlife")) {
2536 unsigned int maxlife;
2537 const char *res;
2538
2539 if (!*args[cur_arg + 1]) {
2540 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2541 file, linenum, args[cur_arg]);
2542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
2544 }
2545
2546 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2547 if (res) {
2548 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2549 file, linenum, *res, args[cur_arg]);
2550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
2552 }
2553 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002554 cur_arg++;
2555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002557 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 +02002558 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }
2562 cur_arg++;
2563 }
Willy Tarreau67402132012-05-31 20:40:20 +02002564 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2566 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 }
2569
Willy Tarreau67402132012-05-31 20:40:20 +02002570 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2572 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002575
Willy Tarreau67402132012-05-31 20:40:20 +02002576 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002577 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2578 file, linenum);
2579 err_code |= ERR_ALERT | ERR_FATAL;
2580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002582 else if (!strcmp(args[0], "persist")) { /* persist */
2583 if (*(args[1]) == 0) {
2584 Alert("parsing [%s:%d] : missing persist method.\n",
2585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002588 }
2589
2590 if (!strncmp(args[1], "rdp-cookie", 10)) {
2591 curproxy->options2 |= PR_O2_RDPC_PRST;
2592
Emeric Brunb982a3d2010-01-04 15:45:53 +01002593 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002594 const char *beg, *end;
2595
2596 beg = args[1] + 11;
2597 end = strchr(beg, ')');
2598
2599 if (!end || end == beg) {
2600 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2601 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002604 }
2605
2606 free(curproxy->rdp_cookie_name);
2607 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2608 curproxy->rdp_cookie_len = end-beg;
2609 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002610 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002611 free(curproxy->rdp_cookie_name);
2612 curproxy->rdp_cookie_name = strdup("msts");
2613 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2614 }
2615 else { /* syntax */
2616 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2617 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002620 }
2621 }
2622 else {
2623 Alert("parsing [%s:%d] : unknown persist method.\n",
2624 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002627 }
2628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002630 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002632 if (curproxy == &defproxy) {
2633 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002640
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002642 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002648 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 curproxy->appsession_name = strdup(args[1]);
2650 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2651 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002652 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2653 if (err) {
2654 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2655 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002658 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002659 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002660
Willy Tarreau51041c72007-09-09 21:56:53 +02002661 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2662 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_ABORT;
2664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002666
2667 cur_arg = 6;
2668 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002669 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2670 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002671 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002672 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002673 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002674 } else if (!strcmp(args[cur_arg], "prefix")) {
2675 curproxy->options2 |= PR_O2_AS_PFX;
2676 } else if (!strcmp(args[cur_arg], "mode")) {
2677 if (!*args[cur_arg + 1]) {
2678 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2679 file, linenum, args[0], args[cur_arg]);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683
2684 cur_arg++;
2685 if (!strcmp(args[cur_arg], "query-string")) {
2686 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2687 curproxy->options2 |= PR_O2_AS_M_QS;
2688 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2689 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2690 curproxy->options2 |= PR_O2_AS_M_PP;
2691 } else {
2692 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002697 cur_arg++;
2698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 } /* Url App Session */
2700 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002701 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002705 if (curproxy == &defproxy) {
2706 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
2709 }
2710
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 if (*(args[4]) == 0) {
2712 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002717 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 curproxy->capture_name = strdup(args[2]);
2719 curproxy->capture_namelen = strlen(curproxy->capture_name);
2720 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002721 curproxy->to_log |= LW_COOKIE;
2722 }
2723 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2724 struct cap_hdr *hdr;
2725
2726 if (curproxy == &defproxy) {
2727 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 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 }
2731
2732 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2733 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2734 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 }
2738
2739 hdr = calloc(sizeof(struct cap_hdr), 1);
2740 hdr->next = curproxy->req_cap;
2741 hdr->name = strdup(args[3]);
2742 hdr->namelen = strlen(args[3]);
2743 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002744 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 hdr->index = curproxy->nb_req_cap++;
2746 curproxy->req_cap = hdr;
2747 curproxy->to_log |= LW_REQHDR;
2748 }
2749 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2750 struct cap_hdr *hdr;
2751
2752 if (curproxy == &defproxy) {
2753 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 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757
2758 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2759 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2760 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 hdr = calloc(sizeof(struct cap_hdr), 1);
2765 hdr->next = curproxy->rsp_cap;
2766 hdr->name = strdup(args[3]);
2767 hdr->namelen = strlen(args[3]);
2768 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002769 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 hdr->index = curproxy->nb_rsp_cap++;
2771 curproxy->rsp_cap = hdr;
2772 curproxy->to_log |= LW_RSPHDR;
2773 }
2774 else {
2775 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
2780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002784
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 if (*(args[1]) == 0) {
2786 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2787 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 }
2791 curproxy->conn_retries = atol(args[1]);
2792 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002793 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002794 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002795
2796 if (curproxy == &defproxy) {
2797 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801
Willy Tarreau20b0de52012-12-24 15:45:22 +01002802 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2803 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2804 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2805 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002806 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002807 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2808 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 +01002809 file, linenum, args[0]);
2810 err_code |= ERR_WARN;
2811 }
2812
Willy Tarreauff011f22011-01-06 17:51:27 +01002813 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002814
Willy Tarreauff011f22011-01-06 17:51:27 +01002815 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002816 err_code |= ERR_ALERT | ERR_ABORT;
2817 goto out;
2818 }
2819
Willy Tarreau5002f572014-04-23 01:32:02 +02002820 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002821 err_code |= warnif_cond_conflicts(rule->cond,
2822 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2823 file, linenum);
2824
Willy Tarreauff011f22011-01-06 17:51:27 +01002825 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002826 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002827 else if (!strcmp(args[0], "http-response")) { /* response access control */
2828 struct http_res_rule *rule;
2829
2830 if (curproxy == &defproxy) {
2831 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835
2836 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2837 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2838 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2839 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2840 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2841 file, linenum, args[0]);
2842 err_code |= ERR_WARN;
2843 }
2844
2845 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2846
2847 if (!rule) {
2848 err_code |= ERR_ALERT | ERR_ABORT;
2849 goto out;
2850 }
2851
2852 err_code |= warnif_cond_conflicts(rule->cond,
2853 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2854 file, linenum);
2855
2856 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2857 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002858 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2859 /* set the header name and length into the proxy structure */
2860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2861 err_code |= ERR_WARN;
2862
2863 if (!*args[1]) {
2864 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2865 file, linenum, args[0]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869
2870 /* set the desired header name */
2871 free(curproxy->server_id_hdr_name);
2872 curproxy->server_id_hdr_name = strdup(args[1]);
2873 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2874 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002875 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002876 if (curproxy == &defproxy) {
2877 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002880 }
2881
Willy Tarreauef6494c2010-01-28 17:12:36 +01002882 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002883 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002887 }
2888
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002889 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2890 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2891 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002894 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002895
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002896 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002897 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002898 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002899 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002900 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002901
Cyril Bonté99ed3272010-01-24 23:29:44 +01002902 if (curproxy == &defproxy) {
2903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002908 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002909 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2910 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002913 }
2914
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002915 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002916 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002917 err_code |= warnif_cond_conflicts(rule->cond,
2918 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2919 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002920 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002921 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002922 struct switching_rule *rule;
2923
Willy Tarreaub099aca2008-10-12 17:26:37 +02002924 if (curproxy == &defproxy) {
2925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002928 }
2929
Willy Tarreau55ea7572007-06-17 19:56:27 +02002930 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002931 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002932
2933 if (*(args[1]) == 0) {
2934 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002937 }
2938
Willy Tarreauf51658d2014-04-23 01:21:56 +02002939 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2940 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2941 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2942 file, linenum, errmsg);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002946
Willy Tarreauf51658d2014-04-23 01:21:56 +02002947 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002948 }
2949
2950 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2951 rule->cond = cond;
2952 rule->be.name = strdup(args[1]);
2953 LIST_INIT(&rule->list);
2954 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2955 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002956 else if (strcmp(args[0], "use-server") == 0) {
2957 struct server_rule *rule;
2958
2959 if (curproxy == &defproxy) {
2960 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2966 err_code |= ERR_WARN;
2967
2968 if (*(args[1]) == 0) {
2969 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973
2974 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2975 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2976 file, linenum, args[0]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
2980
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002981 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2982 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2983 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002988 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002989
2990 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2991 rule->cond = cond;
2992 rule->srv.name = strdup(args[1]);
2993 LIST_INIT(&rule->list);
2994 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2995 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2996 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002997 else if ((!strcmp(args[0], "force-persist")) ||
2998 (!strcmp(args[0], "ignore-persist"))) {
2999 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003000
3001 if (curproxy == &defproxy) {
3002 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3008 err_code |= ERR_WARN;
3009
Willy Tarreauef6494c2010-01-28 17:12:36 +01003010 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003011 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3012 file, linenum, args[0]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003017 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3018 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3019 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003024 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3025 * where force-persist is applied.
3026 */
3027 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003028
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003029 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003030 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003031 if (!strcmp(args[0], "force-persist")) {
3032 rule->type = PERSIST_TYPE_FORCE;
3033 } else {
3034 rule->type = PERSIST_TYPE_IGNORE;
3035 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003036 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003037 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003038 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 else if (!strcmp(args[0], "stick-table")) {
3040 int myidx = 1;
3041
Emeric Brun32da3c42010-09-23 18:39:19 +02003042 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 curproxy->table.type = (unsigned int)-1;
3044 while (*args[myidx]) {
3045 const char *err;
3046
3047 if (strcmp(args[myidx], "size") == 0) {
3048 myidx++;
3049 if (!*(args[myidx])) {
3050 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3051 file, linenum, args[myidx-1]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3056 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3057 file, linenum, *err, args[myidx-1]);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003061 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003063 else if (strcmp(args[myidx], "peers") == 0) {
3064 myidx++;
Godbach50523162013-12-11 19:48:57 +08003065 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003066 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3067 file, linenum, args[myidx-1]);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Godbach50523162013-12-11 19:48:57 +08003070 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003071 curproxy->table.peers.name = strdup(args[myidx++]);
3072 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003073 else if (strcmp(args[myidx], "expire") == 0) {
3074 myidx++;
3075 if (!*(args[myidx])) {
3076 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3077 file, linenum, args[myidx-1]);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
3080 }
3081 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3082 if (err) {
3083 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3084 file, linenum, *err, args[myidx-1]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
3088 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003089 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003090 }
3091 else if (strcmp(args[myidx], "nopurge") == 0) {
3092 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003093 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003094 }
3095 else if (strcmp(args[myidx], "type") == 0) {
3096 myidx++;
3097 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3098 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3099 file, linenum, args[myidx]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003103 /* myidx already points to next arg */
3104 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003105 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003106 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003107 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003108
3109 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003110 nw = args[myidx];
3111 while (*nw) {
3112 /* the "store" keyword supports a comma-separated list */
3113 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003114 sa = NULL; /* store arg */
3115 while (*nw && *nw != ',') {
3116 if (*nw == '(') {
3117 *nw = 0;
3118 sa = ++nw;
3119 while (*nw != ')') {
3120 if (!*nw) {
3121 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3122 file, linenum, args[0], cw);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
3126 nw++;
3127 }
3128 *nw = '\0';
3129 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003130 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003131 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003132 if (*nw)
3133 *nw++ = '\0';
3134 type = stktable_get_data_type(cw);
3135 if (type < 0) {
3136 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140 }
Willy Tarreauac782882010-06-20 10:41:54 +02003141
3142 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3143 switch (err) {
3144 case PE_NONE: break;
3145 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003146 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3147 file, linenum, args[0], cw);
3148 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003149 break;
3150
3151 case PE_ARG_MISSING:
3152 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3153 file, linenum, args[0], cw);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156
3157 case PE_ARG_NOT_USED:
3158 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3159 file, linenum, args[0], cw);
3160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162
3163 default:
3164 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3165 file, linenum, args[0], cw);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003168 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003169 }
3170 myidx++;
3171 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003172 else {
3173 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3174 file, linenum, args[myidx]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003177 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 }
3179
3180 if (!curproxy->table.size) {
3181 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3182 file, linenum);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
3185 }
3186
3187 if (curproxy->table.type == (unsigned int)-1) {
3188 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3189 file, linenum);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
3192 }
3193 }
3194 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003195 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003196 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003197 int myidx = 0;
3198 const char *name = NULL;
3199 int flags;
3200
3201 if (curproxy == &defproxy) {
3202 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3208 err_code |= ERR_WARN;
3209 goto out;
3210 }
3211
3212 myidx++;
3213 if ((strcmp(args[myidx], "store") == 0) ||
3214 (strcmp(args[myidx], "store-request") == 0)) {
3215 myidx++;
3216 flags = STK_IS_STORE;
3217 }
3218 else if (strcmp(args[myidx], "store-response") == 0) {
3219 myidx++;
3220 flags = STK_IS_STORE | STK_ON_RSP;
3221 }
3222 else if (strcmp(args[myidx], "match") == 0) {
3223 myidx++;
3224 flags = STK_IS_MATCH;
3225 }
3226 else if (strcmp(args[myidx], "on") == 0) {
3227 myidx++;
3228 flags = STK_IS_MATCH | STK_IS_STORE;
3229 }
3230 else {
3231 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235
3236 if (*(args[myidx]) == 0) {
3237 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003242 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003243 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003244 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003245 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
3248 }
3249
3250 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003251 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3252 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3253 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003255 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003256 goto out;
3257 }
3258 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003259 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3260 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3261 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003263 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 goto out;
3265 }
3266 }
3267
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003268 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003269 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003270
Emeric Brunb982a3d2010-01-04 15:45:53 +01003271 if (strcmp(args[myidx], "table") == 0) {
3272 myidx++;
3273 name = args[myidx++];
3274 }
3275
Willy Tarreauef6494c2010-01-28 17:12:36 +01003276 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003277 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3278 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3279 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003280 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003281 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003282 goto out;
3283 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003284 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003285 else if (*(args[myidx])) {
3286 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3287 file, linenum, args[0], args[myidx]);
3288 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003289 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003290 goto out;
3291 }
Emeric Brun97679e72010-09-23 17:56:44 +02003292 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003293 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003294 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003295 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003296
Emeric Brunb982a3d2010-01-04 15:45:53 +01003297 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3298 rule->cond = cond;
3299 rule->expr = expr;
3300 rule->flags = flags;
3301 rule->table.name = name ? strdup(name) : NULL;
3302 LIST_INIT(&rule->list);
3303 if (flags & STK_ON_RSP)
3304 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3305 else
3306 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 else if (!strcmp(args[0], "stats")) {
3309 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3310 curproxy->uri_auth = NULL; /* we must detach from the default config */
3311
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003312 if (!*args[1]) {
3313 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003314 } else if (!strcmp(args[1], "admin")) {
3315 struct stats_admin_rule *rule;
3316
3317 if (curproxy == &defproxy) {
3318 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
3322
3323 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3324 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3325 err_code |= ERR_ALERT | ERR_ABORT;
3326 goto out;
3327 }
3328
3329 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3330 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3331 file, linenum, args[0], args[1]);
3332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
3334 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003335 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3336 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3337 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
3341
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003342 err_code |= warnif_cond_conflicts(cond,
3343 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3344 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003345
3346 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3347 rule->cond = cond;
3348 LIST_INIT(&rule->list);
3349 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 } else if (!strcmp(args[1], "uri")) {
3351 if (*(args[2]) == 0) {
3352 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3356 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_ABORT;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360 } else if (!strcmp(args[1], "realm")) {
3361 if (*(args[2]) == 0) {
3362 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3366 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_ABORT;
3368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003370 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003371 unsigned interval;
3372
3373 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3374 if (err) {
3375 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3376 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003379 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3380 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003381 err_code |= ERR_ALERT | ERR_ABORT;
3382 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003383 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003384 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003385 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003386
3387 if (curproxy == &defproxy) {
3388 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392
3393 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3394 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3395 err_code |= ERR_ALERT | ERR_ABORT;
3396 goto out;
3397 }
3398
Willy Tarreauff011f22011-01-06 17:51:27 +01003399 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3400 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003401 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3402 file, linenum, args[0]);
3403 err_code |= ERR_WARN;
3404 }
3405
Willy Tarreauff011f22011-01-06 17:51:27 +01003406 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003407
Willy Tarreauff011f22011-01-06 17:51:27 +01003408 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003409 err_code |= ERR_ALERT | ERR_ABORT;
3410 goto out;
3411 }
3412
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003413 err_code |= warnif_cond_conflicts(rule->cond,
3414 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3415 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003416 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003417
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 } else if (!strcmp(args[1], "auth")) {
3419 if (*(args[2]) == 0) {
3420 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3424 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_ABORT;
3426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428 } else if (!strcmp(args[1], "scope")) {
3429 if (*(args[2]) == 0) {
3430 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3434 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003435 err_code |= ERR_ALERT | ERR_ABORT;
3436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 }
3438 } else if (!strcmp(args[1], "enable")) {
3439 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3440 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_ABORT;
3442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003444 } else if (!strcmp(args[1], "hide-version")) {
3445 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_ABORT;
3448 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003449 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003450 } else if (!strcmp(args[1], "show-legends")) {
3451 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3452 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3453 err_code |= ERR_ALERT | ERR_ABORT;
3454 goto out;
3455 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003456 } else if (!strcmp(args[1], "show-node")) {
3457
3458 if (*args[2]) {
3459 int i;
3460 char c;
3461
3462 for (i=0; args[2][i]; i++) {
3463 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003464 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3465 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003466 break;
3467 }
3468
3469 if (!i || args[2][i]) {
3470 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3471 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3472 file, linenum, args[0], args[1]);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
3476 }
3477
3478 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3479 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3480 err_code |= ERR_ALERT | ERR_ABORT;
3481 goto out;
3482 }
3483 } else if (!strcmp(args[1], "show-desc")) {
3484 char *desc = NULL;
3485
3486 if (*args[2]) {
3487 int i, len=0;
3488 char *d;
3489
Willy Tarreau348acfe2014-04-14 15:00:39 +02003490 for (i = 2; *args[i]; i++)
3491 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003492
3493 desc = d = (char *)calloc(1, len);
3494
Willy Tarreau348acfe2014-04-14 15:00:39 +02003495 d += snprintf(d, desc + len - d, "%s", args[2]);
3496 for (i = 3; *args[i]; i++)
3497 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003498 }
3499
3500 if (!*args[2] && !global.desc)
3501 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3502 file, linenum, args[1]);
3503 else {
3504 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3505 free(desc);
3506 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3507 err_code |= ERR_ALERT | ERR_ABORT;
3508 goto out;
3509 }
3510 free(desc);
3511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003513stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003514 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 +01003515 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 }
3520 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003521 int optnum;
3522
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003523 if (*(args[1]) == '\0') {
3524 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3525 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003529
3530 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3531 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003532 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3533 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3534 file, linenum, cfg_opts[optnum].name);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
Willy Tarreau93893792009-07-23 13:19:11 +02003538 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3539 err_code |= ERR_WARN;
3540 goto out;
3541 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003542
Willy Tarreau3842f002009-06-14 11:39:52 +02003543 curproxy->no_options &= ~cfg_opts[optnum].val;
3544 curproxy->options &= ~cfg_opts[optnum].val;
3545
3546 switch (kwm) {
3547 case KWM_STD:
3548 curproxy->options |= cfg_opts[optnum].val;
3549 break;
3550 case KWM_NO:
3551 curproxy->no_options |= cfg_opts[optnum].val;
3552 break;
3553 case KWM_DEF: /* already cleared */
3554 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003555 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003556
Willy Tarreau93893792009-07-23 13:19:11 +02003557 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003558 }
3559 }
3560
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003561 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3562 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003563 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3564 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3565 file, linenum, cfg_opts2[optnum].name);
3566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
3568 }
Willy Tarreau93893792009-07-23 13:19:11 +02003569 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3570 err_code |= ERR_WARN;
3571 goto out;
3572 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003573
Willy Tarreau3842f002009-06-14 11:39:52 +02003574 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3575 curproxy->options2 &= ~cfg_opts2[optnum].val;
3576
3577 switch (kwm) {
3578 case KWM_STD:
3579 curproxy->options2 |= cfg_opts2[optnum].val;
3580 break;
3581 case KWM_NO:
3582 curproxy->no_options2 |= cfg_opts2[optnum].val;
3583 break;
3584 case KWM_DEF: /* already cleared */
3585 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003586 }
Willy Tarreau93893792009-07-23 13:19:11 +02003587 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003588 }
3589 }
3590
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003591 /* HTTP options override each other. They can be cancelled using
3592 * "no option xxx" which only switches to default mode if the mode
3593 * was this one (useful for cancelling options set in defaults
3594 * sections).
3595 */
3596 if (strcmp(args[1], "httpclose") == 0) {
3597 if (kwm == KWM_STD) {
3598 curproxy->options &= ~PR_O_HTTP_MODE;
3599 curproxy->options |= PR_O_HTTP_PCL;
3600 goto out;
3601 }
3602 else if (kwm == KWM_NO) {
3603 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3604 curproxy->options &= ~PR_O_HTTP_MODE;
3605 goto out;
3606 }
3607 }
3608 else if (strcmp(args[1], "forceclose") == 0) {
3609 if (kwm == KWM_STD) {
3610 curproxy->options &= ~PR_O_HTTP_MODE;
3611 curproxy->options |= PR_O_HTTP_FCL;
3612 goto out;
3613 }
3614 else if (kwm == KWM_NO) {
3615 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3616 curproxy->options &= ~PR_O_HTTP_MODE;
3617 goto out;
3618 }
3619 }
3620 else if (strcmp(args[1], "http-server-close") == 0) {
3621 if (kwm == KWM_STD) {
3622 curproxy->options &= ~PR_O_HTTP_MODE;
3623 curproxy->options |= PR_O_HTTP_SCL;
3624 goto out;
3625 }
3626 else if (kwm == KWM_NO) {
3627 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3628 curproxy->options &= ~PR_O_HTTP_MODE;
3629 goto out;
3630 }
3631 }
3632 else if (strcmp(args[1], "http-keep-alive") == 0) {
3633 if (kwm == KWM_STD) {
3634 curproxy->options &= ~PR_O_HTTP_MODE;
3635 curproxy->options |= PR_O_HTTP_KAL;
3636 goto out;
3637 }
3638 else if (kwm == KWM_NO) {
3639 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3640 curproxy->options &= ~PR_O_HTTP_MODE;
3641 goto out;
3642 }
3643 }
3644 else if (strcmp(args[1], "http-tunnel") == 0) {
3645 if (kwm == KWM_STD) {
3646 curproxy->options &= ~PR_O_HTTP_MODE;
3647 curproxy->options |= PR_O_HTTP_TUN;
3648 goto out;
3649 }
3650 else if (kwm == KWM_NO) {
3651 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3652 curproxy->options &= ~PR_O_HTTP_MODE;
3653 goto out;
3654 }
3655 }
3656
Willy Tarreau3842f002009-06-14 11:39:52 +02003657 if (kwm != KWM_STD) {
3658 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003659 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003662 }
3663
Emeric Brun3a058f32009-06-30 18:26:00 +02003664 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003665 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003667 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003668 if (*(args[2]) != '\0') {
3669 if (!strcmp(args[2], "clf")) {
3670 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003671 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003672 } else {
3673 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003676 }
3677 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003678 if (curproxy->conf.logformat_string != default_http_log_format &&
3679 curproxy->conf.logformat_string != default_tcp_log_format &&
3680 curproxy->conf.logformat_string != clf_http_log_format)
3681 free(curproxy->conf.logformat_string);
3682 curproxy->conf.logformat_string = logformat;
3683
3684 free(curproxy->conf.lfs_file);
3685 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3686 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003687 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003688 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003690 if (curproxy->conf.logformat_string != default_http_log_format &&
3691 curproxy->conf.logformat_string != default_tcp_log_format &&
3692 curproxy->conf.logformat_string != clf_http_log_format)
3693 free(curproxy->conf.logformat_string);
3694 curproxy->conf.logformat_string = default_tcp_log_format;
3695
3696 free(curproxy->conf.lfs_file);
3697 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3698 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 else if (!strcmp(args[1], "tcpka")) {
3701 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003702 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003704
3705 if (curproxy->cap & PR_CAP_FE)
3706 curproxy->options |= PR_O_TCP_CLI_KA;
3707 if (curproxy->cap & PR_CAP_BE)
3708 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 }
3710 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
3713
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003715 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003716 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003717 curproxy->options2 &= ~PR_O2_CHK_ANY;
3718 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 if (!*args[2]) { /* no argument */
3720 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3721 curproxy->check_len = strlen(DEF_CHECK_REQ);
3722 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003723 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 curproxy->check_req = (char *)malloc(reqlen);
3725 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003726 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003728 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 if (*args[4])
3730 reqlen += strlen(args[4]);
3731 else
3732 reqlen += strlen("HTTP/1.0");
3733
3734 curproxy->check_req = (char *)malloc(reqlen);
3735 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003736 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003738 }
3739 else if (!strcmp(args[1], "ssl-hello-chk")) {
3740 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003743
Willy Tarreaua534fea2008-08-03 12:19:50 +02003744 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003745 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003746 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003747 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 }
Willy Tarreau23677902007-05-08 23:50:35 +02003749 else if (!strcmp(args[1], "smtpchk")) {
3750 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003751 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003752 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003753 curproxy->options2 &= ~PR_O2_CHK_ANY;
3754 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003755
3756 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3757 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3758 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3759 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3760 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3761 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3762 curproxy->check_req = (char *)malloc(reqlen);
3763 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3764 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3765 } else {
3766 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3767 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3768 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3769 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3770 }
3771 }
3772 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003773 else if (!strcmp(args[1], "pgsql-check")) {
3774 /* use PostgreSQL request to check servers' health */
3775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3776 err_code |= ERR_WARN;
3777
3778 free(curproxy->check_req);
3779 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003780 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003781 curproxy->options2 |= PR_O2_PGSQL_CHK;
3782
3783 if (*(args[2])) {
3784 int cur_arg = 2;
3785
3786 while (*(args[cur_arg])) {
3787 if (strcmp(args[cur_arg], "user") == 0) {
3788 char * packet;
3789 uint32_t packet_len;
3790 uint32_t pv;
3791
3792 /* suboption header - needs additional argument for it */
3793 if (*(args[cur_arg+1]) == 0) {
3794 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3795 file, linenum, args[0], args[1], args[cur_arg]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
3800 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3801 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3802 pv = htonl(0x30000); /* protocol version 3.0 */
3803
3804 packet = (char*) calloc(1, packet_len);
3805
3806 memcpy(packet + 4, &pv, 4);
3807
3808 /* copy "user" */
3809 memcpy(packet + 8, "user", 4);
3810
3811 /* copy username */
3812 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3813
3814 free(curproxy->check_req);
3815 curproxy->check_req = packet;
3816 curproxy->check_len = packet_len;
3817
3818 packet_len = htonl(packet_len);
3819 memcpy(packet, &packet_len, 4);
3820 cur_arg += 2;
3821 } else {
3822 /* unknown suboption - catchall */
3823 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3824 file, linenum, args[0], args[1]);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
3828 } /* end while loop */
3829 }
3830 }
3831
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003832 else if (!strcmp(args[1], "redis-check")) {
3833 /* use REDIS PING request to check servers' health */
3834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3835 err_code |= ERR_WARN;
3836
3837 free(curproxy->check_req);
3838 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003839 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003840 curproxy->options2 |= PR_O2_REDIS_CHK;
3841
3842 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3843 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3844 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3845 }
3846
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003847 else if (!strcmp(args[1], "mysql-check")) {
3848 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3850 err_code |= ERR_WARN;
3851
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003852 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003853 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003854 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003855 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003856
3857 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3858 * const char mysql40_client_auth_pkt[] = {
3859 * "\x0e\x00\x00" // packet length
3860 * "\x01" // packet number
3861 * "\x00\x00" // client capabilities
3862 * "\x00\x00\x01" // max packet
3863 * "haproxy\x00" // username (null terminated string)
3864 * "\x00" // filler (always 0x00)
3865 * "\x01\x00\x00" // packet length
3866 * "\x00" // packet number
3867 * "\x01" // COM_QUIT command
3868 * };
3869 */
3870
3871 if (*(args[2])) {
3872 int cur_arg = 2;
3873
3874 while (*(args[cur_arg])) {
3875 if (strcmp(args[cur_arg], "user") == 0) {
3876 char *mysqluser;
3877 int packetlen, reqlen, userlen;
3878
3879 /* suboption header - needs additional argument for it */
3880 if (*(args[cur_arg+1]) == 0) {
3881 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3882 file, linenum, args[0], args[1], args[cur_arg]);
3883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
3885 }
3886 mysqluser = args[cur_arg + 1];
3887 userlen = strlen(mysqluser);
3888 packetlen = userlen + 7;
3889 reqlen = packetlen + 9;
3890
3891 free(curproxy->check_req);
3892 curproxy->check_req = (char *)calloc(1, reqlen);
3893 curproxy->check_len = reqlen;
3894
3895 snprintf(curproxy->check_req, 4, "%c%c%c",
3896 ((unsigned char) packetlen & 0xff),
3897 ((unsigned char) (packetlen >> 8) & 0xff),
3898 ((unsigned char) (packetlen >> 16) & 0xff));
3899
3900 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003901 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003902 curproxy->check_req[8] = 1;
3903 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3904 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3905 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3906 cur_arg += 2;
3907 } else {
3908 /* unknown suboption - catchall */
3909 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3910 file, linenum, args[0], args[1]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914 } /* end while loop */
3915 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003916 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003917 else if (!strcmp(args[1], "ldap-check")) {
3918 /* use LDAP request to check servers' health */
3919 free(curproxy->check_req);
3920 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003921 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003922 curproxy->options2 |= PR_O2_LDAP_CHK;
3923
3924 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3925 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3926 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3927 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003928 else if (!strcmp(args[1], "tcp-check")) {
3929 /* use raw TCPCHK send/expect to check servers' health */
3930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3931 err_code |= ERR_WARN;
3932
3933 free(curproxy->check_req);
3934 curproxy->check_req = NULL;
3935 curproxy->options2 &= ~PR_O2_CHK_ANY;
3936 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3937 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003938 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003939 int cur_arg;
3940
3941 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3942 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003943 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003944
Willy Tarreau87cf5142011-08-19 22:57:24 +02003945 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003946
3947 free(curproxy->fwdfor_hdr_name);
3948 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3949 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3950
3951 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3952 cur_arg = 2;
3953 while (*(args[cur_arg])) {
3954 if (!strcmp(args[cur_arg], "except")) {
3955 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003956 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003957 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3958 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003961 }
3962 /* flush useless bits */
3963 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003964 cur_arg += 2;
3965 } else if (!strcmp(args[cur_arg], "header")) {
3966 /* suboption header - needs additional argument for it */
3967 if (*(args[cur_arg+1]) == 0) {
3968 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3969 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003972 }
3973 free(curproxy->fwdfor_hdr_name);
3974 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3975 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3976 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003977 } else if (!strcmp(args[cur_arg], "if-none")) {
3978 curproxy->options &= ~PR_O_FF_ALWAYS;
3979 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003980 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003981 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003982 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003983 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003986 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003987 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003988 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003989 else if (!strcmp(args[1], "originalto")) {
3990 int cur_arg;
3991
3992 /* insert x-original-to field, but not for the IP address listed as an except.
3993 * set default options (ie: bitfield, header name, etc)
3994 */
3995
3996 curproxy->options |= PR_O_ORGTO;
3997
3998 free(curproxy->orgto_hdr_name);
3999 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4000 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4001
Willy Tarreau87cf5142011-08-19 22:57:24 +02004002 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004003 cur_arg = 2;
4004 while (*(args[cur_arg])) {
4005 if (!strcmp(args[cur_arg], "except")) {
4006 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004007 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 +02004008 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4009 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004012 }
4013 /* flush useless bits */
4014 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4015 cur_arg += 2;
4016 } else if (!strcmp(args[cur_arg], "header")) {
4017 /* suboption header - needs additional argument for it */
4018 if (*(args[cur_arg+1]) == 0) {
4019 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4020 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004023 }
4024 free(curproxy->orgto_hdr_name);
4025 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4026 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4027 cur_arg += 2;
4028 } else {
4029 /* unknown suboption - catchall */
4030 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4031 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004034 }
4035 } /* end while loop */
4036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 else {
4038 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
Willy Tarreau93893792009-07-23 13:19:11 +02004042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004044 else if (!strcmp(args[0], "default_backend")) {
4045 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004047
4048 if (*(args[1]) == 0) {
4049 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004052 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004053 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004054 curproxy->defbe.name = strdup(args[1]);
4055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004057 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004059
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004060 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004062 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 /* enable reconnections to dispatch */
4064 curproxy->options |= PR_O_REDISP;
4065 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004066 else if (!strcmp(args[0], "http-check")) {
4067 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004069
4070 if (strcmp(args[1], "disable-on-404") == 0) {
4071 /* enable a graceful server shutdown on an HTTP 404 response */
4072 curproxy->options |= PR_O_DISABLE404;
4073 }
Willy Tarreauef781042010-01-27 11:53:01 +01004074 else if (strcmp(args[1], "send-state") == 0) {
4075 /* enable emission of the apparent state of a server in HTTP checks */
4076 curproxy->options2 |= PR_O2_CHK_SNDST;
4077 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004078 else if (strcmp(args[1], "expect") == 0) {
4079 const char *ptr_arg;
4080 int cur_arg;
4081
4082 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4083 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087
4088 cur_arg = 2;
4089 /* consider exclamation marks, sole or at the beginning of a word */
4090 while (*(ptr_arg = args[cur_arg])) {
4091 while (*ptr_arg == '!') {
4092 curproxy->options2 ^= PR_O2_EXP_INV;
4093 ptr_arg++;
4094 }
4095 if (*ptr_arg)
4096 break;
4097 cur_arg++;
4098 }
4099 /* now ptr_arg points to the beginning of a word past any possible
4100 * exclamation mark, and cur_arg is the argument which holds this word.
4101 */
4102 if (strcmp(ptr_arg, "status") == 0) {
4103 if (!*(args[cur_arg + 1])) {
4104 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4105 file, linenum, args[0], args[1], ptr_arg);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004110 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004111 curproxy->expect_str = strdup(args[cur_arg + 1]);
4112 }
4113 else if (strcmp(ptr_arg, "string") == 0) {
4114 if (!*(args[cur_arg + 1])) {
4115 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4116 file, linenum, args[0], args[1], ptr_arg);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 }
4120 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004121 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004122 curproxy->expect_str = strdup(args[cur_arg + 1]);
4123 }
4124 else if (strcmp(ptr_arg, "rstatus") == 0) {
4125 if (!*(args[cur_arg + 1])) {
4126 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4127 file, linenum, args[0], args[1], ptr_arg);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004132 free(curproxy->expect_str);
4133 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4134 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004135 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4136 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4137 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4138 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
4141 }
4142 }
4143 else if (strcmp(ptr_arg, "rstring") == 0) {
4144 if (!*(args[cur_arg + 1])) {
4145 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4146 file, linenum, args[0], args[1], ptr_arg);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004151 free(curproxy->expect_str);
4152 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4153 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004154 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4155 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4156 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4157 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
4161 }
4162 else {
4163 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4164 file, linenum, args[0], args[1], ptr_arg);
4165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
4167 }
4168 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004169 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004170 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 +02004171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004173 }
4174 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004175 else if (!strcmp(args[0], "tcp-check")) {
4176 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4177 err_code |= ERR_WARN;
4178
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004179 if (strcmp(args[1], "connect") == 0) {
4180 const char *ptr_arg;
4181 int cur_arg;
4182 struct tcpcheck_rule *tcpcheck;
4183 struct list *l;
4184
4185 /* check if first rule is also a 'connect' action */
4186 l = (struct list *)&curproxy->tcpcheck_rules;
4187 if (l->p != l->n) {
4188 tcpcheck = (struct tcpcheck_rule *)l->n;
4189 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4190 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4191 file, linenum);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
4195 }
4196
4197 cur_arg = 2;
4198 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4199 tcpcheck->action = TCPCHK_ACT_CONNECT;
4200
4201 /* parsing each parameters to fill up the rule */
4202 while (*(ptr_arg = args[cur_arg])) {
4203 /* tcp port */
4204 if (strcmp(args[cur_arg], "port") == 0) {
4205 if ( (atol(args[cur_arg + 1]) > 65535) ||
4206 (atol(args[cur_arg + 1]) < 1) ){
4207 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4208 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212 tcpcheck->port = atol(args[cur_arg + 1]);
4213 cur_arg += 2;
4214 }
4215 /* send proxy protocol */
4216 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4217 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4218 cur_arg++;
4219 }
4220#ifdef USE_OPENSSL
4221 else if (strcmp(args[cur_arg], "ssl") == 0) {
4222 curproxy->options |= PR_O_TCPCHK_SSL;
4223 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4224 cur_arg++;
4225 }
4226#endif /* USE_OPENSSL */
4227 else {
4228#ifdef USE_OPENSSL
4229 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4230#else /* USE_OPENSSL */
4231 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4232#endif /* USE_OPENSSL */
4233 file, linenum, args[0], args[1], args[cur_arg]);
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
4236 }
4237
4238 }
4239
4240 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4241 }
4242 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004243 if (! *(args[2]) ) {
4244 /* SEND string expected */
4245 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4246 file, linenum, args[0], args[1], args[2]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 } else {
4250 struct tcpcheck_rule *tcpcheck;
4251
4252 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4253
4254 tcpcheck->action = TCPCHK_ACT_SEND;
4255 tcpcheck->string_len = strlen(args[2]);
4256 tcpcheck->string = strdup(args[2]);
4257 tcpcheck->expect_regex = NULL;
4258
4259 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4260 }
4261 }
4262 else if (strcmp(args[1], "send-binary") == 0) {
4263 if (! *(args[2]) ) {
4264 /* SEND binary string expected */
4265 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4266 file, linenum, args[0], args[1], args[2]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 } else {
4270 struct tcpcheck_rule *tcpcheck;
4271 char *err = NULL;
4272
4273 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4274
4275 tcpcheck->action = TCPCHK_ACT_SEND;
4276 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4277 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4278 file, linenum, args[0], args[1], args[2], err);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282 tcpcheck->expect_regex = NULL;
4283
4284 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4285 }
4286 }
4287 else if (strcmp(args[1], "expect") == 0) {
4288 const char *ptr_arg;
4289 int cur_arg;
4290 int inverse = 0;
4291
4292 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4293 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297
4298 cur_arg = 2;
4299 /* consider exclamation marks, sole or at the beginning of a word */
4300 while (*(ptr_arg = args[cur_arg])) {
4301 while (*ptr_arg == '!') {
4302 inverse = !inverse;
4303 ptr_arg++;
4304 }
4305 if (*ptr_arg)
4306 break;
4307 cur_arg++;
4308 }
4309 /* now ptr_arg points to the beginning of a word past any possible
4310 * exclamation mark, and cur_arg is the argument which holds this word.
4311 */
4312 if (strcmp(ptr_arg, "binary") == 0) {
4313 if (!*(args[cur_arg + 1])) {
4314 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4315 file, linenum, args[0], args[1], ptr_arg);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319 struct tcpcheck_rule *tcpcheck;
4320 char *err = NULL;
4321
4322 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4323
4324 tcpcheck->action = TCPCHK_ACT_EXPECT;
4325 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4326 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4327 file, linenum, args[0], args[1], args[2], err);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331 tcpcheck->expect_regex = NULL;
4332 tcpcheck->inverse = inverse;
4333
4334 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4335 }
4336 else if (strcmp(ptr_arg, "string") == 0) {
4337 if (!*(args[cur_arg + 1])) {
4338 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4339 file, linenum, args[0], args[1], ptr_arg);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 struct tcpcheck_rule *tcpcheck;
4344
4345 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4346
4347 tcpcheck->action = TCPCHK_ACT_EXPECT;
4348 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4349 tcpcheck->string = strdup(args[cur_arg + 1]);
4350 tcpcheck->expect_regex = NULL;
4351 tcpcheck->inverse = inverse;
4352
4353 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4354 }
4355 else if (strcmp(ptr_arg, "rstring") == 0) {
4356 if (!*(args[cur_arg + 1])) {
4357 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4358 file, linenum, args[0], args[1], ptr_arg);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362 struct tcpcheck_rule *tcpcheck;
4363
4364 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4365
4366 tcpcheck->action = TCPCHK_ACT_EXPECT;
4367 tcpcheck->string_len = 0;
4368 tcpcheck->string = NULL;
4369 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4370 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4371 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4372 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376 tcpcheck->inverse = inverse;
4377
4378 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4379 }
4380 else {
4381 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4382 file, linenum, args[0], args[1], ptr_arg);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
4386 }
4387 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004388 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004393 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004394 if (curproxy == &defproxy) {
4395 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004398 }
4399
Willy Tarreaub80c2302007-11-30 20:51:32 +01004400 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004402
4403 if (strcmp(args[1], "fail") == 0) {
4404 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004405 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004406 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4407 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004410 }
4411
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004412 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4413 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4414 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004417 }
4418 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4419 }
4420 else {
4421 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004424 }
4425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426#ifdef TPROXY
4427 else if (!strcmp(args[0], "transparent")) {
4428 /* enable transparent proxy connections */
4429 curproxy->options |= PR_O_TRANSP;
4430 }
4431#endif
4432 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004433 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004435
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 if (*(args[1]) == 0) {
4437 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 }
4441 curproxy->maxconn = atol(args[1]);
4442 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004443 else if (!strcmp(args[0], "backlog")) { /* backlog */
4444 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004446
4447 if (*(args[1]) == 0) {
4448 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004451 }
4452 curproxy->backlog = atol(args[1]);
4453 }
Willy Tarreau86034312006-12-29 00:10:33 +01004454 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004455 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004457
Willy Tarreau86034312006-12-29 00:10:33 +01004458 if (*(args[1]) == 0) {
4459 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004462 }
4463 curproxy->fullconn = atol(args[1]);
4464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4466 if (*(args[1]) == 0) {
4467 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004471 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4472 if (err) {
4473 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4474 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004477 }
4478 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
4480 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004481 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004482 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004483 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004484
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 if (curproxy == &defproxy) {
4486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004490 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004491 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004492
Willy Tarreau902636f2013-03-10 19:44:48 +01004493 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004494 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004495 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004496 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004497 goto out;
4498 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004499
4500 proto = protocol_by_family(sk->ss_family);
4501 if (!proto || !proto->connect) {
4502 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4503 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
4507
4508 if (port1 != port2) {
4509 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4510 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004514
4515 if (!port1) {
4516 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4517 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
4520 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004521
Willy Tarreaud5191e72010-02-09 20:50:45 +01004522 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004523 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524 }
4525 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004528
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004529 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4530 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004535 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004536 /**
4537 * The syntax for hash-type config element is
4538 * hash-type {map-based|consistent} [[<algo>] avalanche]
4539 *
4540 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4541 */
4542 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004543
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4545 err_code |= ERR_WARN;
4546
4547 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004548 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4549 }
4550 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004551 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4552 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004553 else if (strcmp(args[1], "avalanche") == 0) {
4554 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]);
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004557 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004558 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004559 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
Bhaskar98634f02013-10-29 23:30:51 -04004563
4564 /* set the hash function to use */
4565 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004566 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004567 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004568
4569 /* if consistent with no argument, then avalanche modifier is also applied */
4570 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4571 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004572 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004573 /* set the hash function */
4574 if (!strcmp(args[2], "sdbm")) {
4575 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4576 }
4577 else if (!strcmp(args[2], "djb2")) {
4578 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004579 } else if (!strcmp(args[2], "wt6")) {
4580 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004581 }
4582 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004583 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 -05004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
4586 }
4587
4588 /* set the hash modifier */
4589 if (!strcmp(args[3], "avalanche")) {
4590 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4591 }
4592 else if (*args[3]) {
4593 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
4596 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004597 }
William Lallemanda73203e2012-03-12 12:48:57 +01004598 }
William Lallemanda73203e2012-03-12 12:48:57 +01004599 else if (strcmp(args[0], "unique-id-format") == 0) {
4600 if (!*(args[1])) {
4601 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
William Lallemand3203ff42012-11-11 17:30:56 +01004605 if (*(args[2])) {
4606 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004610 free(curproxy->conf.uniqueid_format_string);
4611 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004612
Willy Tarreau62a61232013-04-12 18:13:46 +02004613 free(curproxy->conf.uif_file);
4614 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4615 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004616 }
William Lallemanda73203e2012-03-12 12:48:57 +01004617
4618 else if (strcmp(args[0], "unique-id-header") == 0) {
4619 if (!*(args[1])) {
4620 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624 free(curproxy->header_unique_id);
4625 curproxy->header_unique_id = strdup(args[1]);
4626 }
4627
William Lallemand723b73a2012-02-08 16:37:49 +01004628 else if (strcmp(args[0], "log-format") == 0) {
4629 if (!*(args[1])) {
4630 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
4633 }
William Lallemand3203ff42012-11-11 17:30:56 +01004634 if (*(args[2])) {
4635 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
4638 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004639
Willy Tarreau62a61232013-04-12 18:13:46 +02004640 if (curproxy->conf.logformat_string != default_http_log_format &&
4641 curproxy->conf.logformat_string != default_tcp_log_format &&
4642 curproxy->conf.logformat_string != clf_http_log_format)
4643 free(curproxy->conf.logformat_string);
4644 curproxy->conf.logformat_string = strdup(args[1]);
4645
4646 free(curproxy->conf.lfs_file);
4647 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4648 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004649
4650 /* get a chance to improve log-format error reporting by
4651 * reporting the correct line-number when possible.
4652 */
4653 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4654 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4655 file, linenum, curproxy->id);
4656 err_code |= ERR_WARN;
4657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 }
William Lallemand723b73a2012-02-08 16:37:49 +01004659
William Lallemand0f99e342011-10-12 17:50:54 +02004660 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4661 /* delete previous herited or defined syslog servers */
4662 struct logsrv *back;
4663
4664 if (*(args[1]) != 0) {
4665 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669
William Lallemand723b73a2012-02-08 16:37:49 +01004670 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4671 LIST_DEL(&tmplogsrv->list);
4672 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004673 }
4674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004676 struct logsrv *logsrv;
4677
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004679 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004680 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004681 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004682 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004683 LIST_INIT(&node->list);
4684 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
4687 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004688 struct sockaddr_storage *sk;
4689 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004690
4691 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692
William Lallemand0f99e342011-10-12 17:50:54 +02004693 logsrv->facility = get_log_facility(args[2]);
4694 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
4698
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
4700
William Lallemand0f99e342011-10-12 17:50:54 +02004701 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004703 logsrv->level = get_log_level(args[3]);
4704 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 }
4710 }
4711
William Lallemand0f99e342011-10-12 17:50:54 +02004712 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004713 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004714 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004715 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004716 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004720 }
4721 }
4722
Willy Tarreau902636f2013-03-10 19:44:48 +01004723 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004724 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004725 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004726 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004727 goto out;
4728 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004729
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004730 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004731
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004732 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733 if (port1 != port2) {
4734 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4735 file, linenum, args[0], args[1]);
4736 err_code |= ERR_ALERT | ERR_FATAL;
4737 goto out;
4738 }
4739
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004740 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004741 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 }
William Lallemand0f99e342011-10-12 17:50:54 +02004743
4744 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 }
4746 else {
4747 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4748 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
4752 }
4753 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004754 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004755 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004756 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004757 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004758
Willy Tarreau977b8e42006-12-29 14:19:17 +01004759 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004761
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004763 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4764 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004768
4769 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004770 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4771 free(curproxy->conn_src.iface_name);
4772 curproxy->conn_src.iface_name = NULL;
4773 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004774
Willy Tarreau902636f2013-03-10 19:44:48 +01004775 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004776 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004777 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004778 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004779 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004780 goto out;
4781 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004782
4783 proto = protocol_by_family(sk->ss_family);
4784 if (!proto || !proto->connect) {
4785 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004786 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004790
4791 if (port1 != port2) {
4792 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4793 file, linenum, args[0], args[1]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797
Willy Tarreauef9a3602012-12-08 22:29:20 +01004798 curproxy->conn_src.source_addr = *sk;
4799 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004800
4801 cur_arg = 2;
4802 while (*(args[cur_arg])) {
4803 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004804#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4805#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004806 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004807 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4808 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004811 }
4812#endif
4813 if (!*args[cur_arg + 1]) {
4814 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4815 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004818 }
4819
4820 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004821 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4822 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004823 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004824 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4825 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004826 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4827 char *name, *end;
4828
4829 name = args[cur_arg+1] + 7;
4830 while (isspace(*name))
4831 name++;
4832
4833 end = name;
4834 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4835 end++;
4836
Willy Tarreauef9a3602012-12-08 22:29:20 +01004837 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4838 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4839 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4840 curproxy->conn_src.bind_hdr_len = end - name;
4841 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4842 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4843 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004844
4845 /* now look for an occurrence number */
4846 while (isspace(*end))
4847 end++;
4848 if (*end == ',') {
4849 end++;
4850 name = end;
4851 if (*end == '-')
4852 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004853 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004854 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004855 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004856 }
4857
Willy Tarreauef9a3602012-12-08 22:29:20 +01004858 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004859 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4860 " occurrences values smaller than %d.\n",
4861 file, linenum, MAX_HDR_HISTORY);
4862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004865 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004866 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004867
Willy Tarreau902636f2013-03-10 19:44:48 +01004868 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004869 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004870 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004871 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004872 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004873 goto out;
4874 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004875
4876 proto = protocol_by_family(sk->ss_family);
4877 if (!proto || !proto->connect) {
4878 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4879 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004883
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004884 if (port1 != port2) {
4885 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4886 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004890 curproxy->conn_src.tproxy_addr = *sk;
4891 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004892 }
4893 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004894#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004895 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004896#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004897#else /* no TPROXY support */
4898 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004899 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902#endif
4903 cur_arg += 2;
4904 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004905 }
4906
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004907 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4908#ifdef SO_BINDTODEVICE
4909 if (!*args[cur_arg + 1]) {
4910 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004914 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004915 free(curproxy->conn_src.iface_name);
4916 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4917 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004918 global.last_checks |= LSTCHK_NETADM;
4919#else
4920 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4921 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004924#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004925 cur_arg += 2;
4926 continue;
4927 }
4928 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004929 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004934 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4935 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4936 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947
4948 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004949 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004950 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
4954 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004956 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004957 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
4961 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004963 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004964 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004970 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004971 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004977 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004982 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004984 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004985 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004987 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004988 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004989 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004992 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004995 }
4996 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004998 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004999 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005001 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010
5011 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005012 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005013 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005014 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
5017 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005018 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005019 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005020 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
5024 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005026 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005027 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005033 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005034 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
5038 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005040 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005041 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005045 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005047 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005048 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005050 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005053 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005054
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 if (curproxy == &defproxy) {
5056 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005060 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 if (*(args[1]) == 0) {
5064 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005068
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005069 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005070 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5071 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5072 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005076 err_code |= warnif_cond_conflicts(cond,
5077 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5078 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005079 }
5080 else if (*args[2]) {
5081 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5082 file, linenum, args[0], args[2]);
5083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
5085 }
5086
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005087 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005088 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005089 wl->s = strdup(args[1]);
5090 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005091 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
5093 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5096 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005100
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005102 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005103 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005109 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005110 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005111 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
5114 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005116 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005117 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
5121 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005122 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5124 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 }
5128
Willy Tarreauade5ec42010-01-28 19:33:49 +01005129 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005130 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005131 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005132 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 }
5135 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005136 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005137 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005138 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 }
5142 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005144 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005145 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005150 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005151
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 if (curproxy == &defproxy) {
5153 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 if (*(args[1]) == 0) {
5161 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
5165
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005166 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005167 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5168 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5169 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
5172 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005173 err_code |= warnif_cond_conflicts(cond,
5174 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5175 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005176 }
5177 else if (*args[2]) {
5178 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5179 file, linenum, args[0], args[2]);
5180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005184 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005185 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005186 wl->s = strdup(args[1]);
5187 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
5189 else if (!strcmp(args[0], "errorloc") ||
5190 !strcmp(args[0], "errorloc302") ||
5191 !strcmp(args[0], "errorloc303")) { /* error location */
5192 int errnum, errlen;
5193 char *err;
5194
Willy Tarreau977b8e42006-12-29 14:19:17 +01005195 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005197
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005199 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
5203
5204 errnum = atol(args[1]);
5205 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005206 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5207 err = malloc(errlen);
5208 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005210 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5211 err = malloc(errlen);
5212 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
5214
Willy Tarreau0f772532006-12-23 20:51:41 +01005215 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5216 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005217 chunk_destroy(&curproxy->errmsg[rc]);
5218 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005219 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005222
5223 if (rc >= HTTP_ERR_SIZE) {
5224 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5225 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 free(err);
5227 }
5228 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5230 int errnum, errlen, fd;
5231 char *err;
5232 struct stat stat;
5233
5234 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005236
5237 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005238 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005241 }
5242
5243 fd = open(args[2], O_RDONLY);
5244 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5245 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5246 file, linenum, args[2], args[1]);
5247 if (fd >= 0)
5248 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005251 }
5252
Willy Tarreau27a674e2009-08-17 07:23:33 +02005253 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005254 errlen = stat.st_size;
5255 } else {
5256 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005257 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005258 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005259 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005260 }
5261
5262 err = malloc(errlen); /* malloc() must succeed during parsing */
5263 errnum = read(fd, err, errlen);
5264 if (errnum != errlen) {
5265 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5266 file, linenum, args[2], args[1]);
5267 close(fd);
5268 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005271 }
5272 close(fd);
5273
5274 errnum = atol(args[1]);
5275 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5276 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005277 chunk_destroy(&curproxy->errmsg[rc]);
5278 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005279 break;
5280 }
5281 }
5282
5283 if (rc >= HTTP_ERR_SIZE) {
5284 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5285 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005287 free(err);
5288 }
5289 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005290 else if (!strcmp(args[0], "compression")) {
5291 struct comp *comp;
5292 if (curproxy->comp == NULL) {
5293 comp = calloc(1, sizeof(struct comp));
5294 curproxy->comp = comp;
5295 } else {
5296 comp = curproxy->comp;
5297 }
5298
5299 if (!strcmp(args[1], "algo")) {
5300 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005301 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005302
William Lallemand82fe75c2012-10-23 10:25:10 +02005303 cur_arg = 2;
5304 if (!*args[cur_arg]) {
5305 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5306 file, linenum, args[0]);
5307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309 }
5310 while (*(args[cur_arg])) {
5311 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5312 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5313 file, linenum, args[0], args[cur_arg]);
5314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
5316 }
William Lallemand552df672012-11-07 13:21:47 +01005317 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5318 curproxy->comp->algos->end(&ctx);
5319 } else {
5320 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5321 file, linenum, args[0], args[cur_arg]);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005325 cur_arg ++;
5326 continue;
5327 }
5328 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005329 else if (!strcmp(args[1], "offload")) {
5330 comp->offload = 1;
5331 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005332 else if (!strcmp(args[1], "type")) {
5333 int cur_arg;
5334 cur_arg = 2;
5335 if (!*args[cur_arg]) {
5336 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5337 file, linenum, args[0]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 while (*(args[cur_arg])) {
5342 comp_append_type(comp, args[cur_arg]);
5343 cur_arg ++;
5344 continue;
5345 }
5346 }
5347 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005348 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005349 file, linenum, args[0]);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
5353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005355 struct cfg_kw_list *kwl;
5356 int index;
5357
5358 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5359 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5360 if (kwl->kw[index].section != CFG_LISTEN)
5361 continue;
5362 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5363 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005364 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005365 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005366 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005369 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005370 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005371 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_WARN;
5373 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005374 }
Willy Tarreau93893792009-07-23 13:19:11 +02005375 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005376 }
5377 }
5378 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005379
Willy Tarreau6daf3432008-01-22 16:44:08 +01005380 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
Willy Tarreau93893792009-07-23 13:19:11 +02005384 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005385 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005386 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387}
5388
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005389int
5390cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5391{
5392
5393 int err_code = 0;
5394 const char *err;
5395
5396 if (!strcmp(args[0], "userlist")) { /* new userlist */
5397 struct userlist *newul;
5398
5399 if (!*args[1]) {
5400 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5401 file, linenum, args[0]);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
5405
5406 err = invalid_char(args[1]);
5407 if (err) {
5408 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5409 file, linenum, *err, args[0], args[1]);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413
5414 for (newul = userlist; newul; newul = newul->next)
5415 if (!strcmp(newul->name, args[1])) {
5416 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5417 file, linenum, args[1]);
5418 err_code |= ERR_WARN;
5419 goto out;
5420 }
5421
5422 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5423 if (!newul) {
5424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5425 err_code |= ERR_ALERT | ERR_ABORT;
5426 goto out;
5427 }
5428
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005429 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005430 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005431 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5432 err_code |= ERR_ALERT | ERR_ABORT;
5433 goto out;
5434 }
5435
5436 newul->next = userlist;
5437 userlist = newul;
5438
5439 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005440 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005441 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005442 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005443
5444 if (!*args[1]) {
5445 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5446 file, linenum, args[0]);
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 }
5450
5451 err = invalid_char(args[1]);
5452 if (err) {
5453 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5454 file, linenum, *err, args[0], args[1]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
5458
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005459 for (ag = userlist->groups; ag; ag = ag->next)
5460 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005461 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5462 file, linenum, args[1], userlist->name);
5463 err_code |= ERR_ALERT;
5464 goto out;
5465 }
5466
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005467 ag = calloc(1, sizeof(*ag));
5468 if (!ag) {
5469 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5470 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005471 goto out;
5472 }
5473
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005474 ag->name = strdup(args[1]);
5475 if (!ag) {
5476 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5477 err_code |= ERR_ALERT | ERR_ABORT;
5478 goto out;
5479 }
5480
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005481 cur_arg = 2;
5482
5483 while (*args[cur_arg]) {
5484 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005485 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005486 cur_arg += 2;
5487 continue;
5488 } else {
5489 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5490 file, linenum, args[0]);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
5494 }
5495
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005496 ag->next = userlist->groups;
5497 userlist->groups = ag;
5498
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005499 } else if (!strcmp(args[0], "user")) { /* new user */
5500 struct auth_users *newuser;
5501 int cur_arg;
5502
5503 if (!*args[1]) {
5504 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5505 file, linenum, args[0]);
5506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
5509
5510 for (newuser = userlist->users; newuser; newuser = newuser->next)
5511 if (!strcmp(newuser->user, args[1])) {
5512 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5513 file, linenum, args[1], userlist->name);
5514 err_code |= ERR_ALERT;
5515 goto out;
5516 }
5517
5518 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5519 if (!newuser) {
5520 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5521 err_code |= ERR_ALERT | ERR_ABORT;
5522 goto out;
5523 }
5524
5525 newuser->user = strdup(args[1]);
5526
5527 newuser->next = userlist->users;
5528 userlist->users = newuser;
5529
5530 cur_arg = 2;
5531
5532 while (*args[cur_arg]) {
5533 if (!strcmp(args[cur_arg], "password")) {
5534#ifndef CONFIG_HAP_CRYPT
5535 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5536 file, linenum);
5537 err_code |= ERR_ALERT;
5538#endif
5539 newuser->pass = strdup(args[cur_arg + 1]);
5540 cur_arg += 2;
5541 continue;
5542 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5543 newuser->pass = strdup(args[cur_arg + 1]);
5544 newuser->flags |= AU_O_INSECURE;
5545 cur_arg += 2;
5546 continue;
5547 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005548 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005549 cur_arg += 2;
5550 continue;
5551 } else {
5552 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5553 file, linenum, args[0]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557 }
5558 } else {
5559 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 }
5562
5563out:
5564 return err_code;
5565}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566
5567/*
5568 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005569 * Returns the error code, 0 if OK, or any combination of :
5570 * - ERR_ABORT: must abort ASAP
5571 * - ERR_FATAL: we can continue parsing but not start the service
5572 * - ERR_WARN: a warning has been emitted
5573 * - ERR_ALERT: an alert has been emitted
5574 * Only the two first ones can stop processing, the two others are just
5575 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005577int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005579 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 FILE *f;
5581 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005582 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005583 struct cfg_section *cs = NULL;
5584 struct cfg_section *ics;
5585
5586 /* Register internal sections */
5587 if (!cfg_register_section("listen", cfg_parse_listen) ||
5588 !cfg_register_section("frontend", cfg_parse_listen) ||
5589 !cfg_register_section("backend", cfg_parse_listen) ||
5590 !cfg_register_section("ruleset", cfg_parse_listen) ||
5591 !cfg_register_section("defaults", cfg_parse_listen) ||
5592 !cfg_register_section("global", cfg_parse_global) ||
5593 !cfg_register_section("userlist", cfg_parse_users) ||
5594 !cfg_register_section("peers", cfg_parse_peers))
5595 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 if ((f=fopen(file,"r")) == NULL)
5598 return -1;
5599
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005600 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005601 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005602 char *end;
5603 char *args[MAX_LINE_ARGS + 1];
5604 char *line = thisline;
5605
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 linenum++;
5607
5608 end = line + strlen(line);
5609
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005610 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5611 /* Check if we reached the limit and the last char is not \n.
5612 * Watch out for the last line without the terminating '\n'!
5613 */
5614 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005615 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005616 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005617 }
5618
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005620 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 line++;
5622
5623 arg = 0;
5624 args[arg] = line;
5625
5626 while (*line && arg < MAX_LINE_ARGS) {
5627 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5628 * C equivalent value. Other combinations left unchanged (eg: \1).
5629 */
5630 if (*line == '\\') {
5631 int skip = 0;
5632 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5633 *line = line[1];
5634 skip = 1;
5635 }
5636 else if (line[1] == 'r') {
5637 *line = '\r';
5638 skip = 1;
5639 }
5640 else if (line[1] == 'n') {
5641 *line = '\n';
5642 skip = 1;
5643 }
5644 else if (line[1] == 't') {
5645 *line = '\t';
5646 skip = 1;
5647 }
5648 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005649 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 unsigned char hex1, hex2;
5651 hex1 = toupper(line[2]) - '0';
5652 hex2 = toupper(line[3]) - '0';
5653 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5654 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5655 *line = (hex1<<4) + hex2;
5656 skip = 3;
5657 }
5658 else {
5659 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 }
5663 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005664 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 end -= skip;
5666 }
5667 line++;
5668 }
5669 else if (*line == '#' || *line == '\n' || *line == '\r') {
5670 /* end of string, end of loop */
5671 *line = 0;
5672 break;
5673 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005674 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005676 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005677 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 line++;
5679 args[++arg] = line;
5680 }
5681 else {
5682 line++;
5683 }
5684 }
5685
5686 /* empty line */
5687 if (!**args)
5688 continue;
5689
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005690 if (*line) {
5691 /* we had to stop due to too many args.
5692 * Let's terminate the string, print the offending part then cut the
5693 * last arg.
5694 */
5695 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5696 line++;
5697 *line = '\0';
5698
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005699 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005700 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005701 err_code |= ERR_ALERT | ERR_FATAL;
5702 args[arg] = line;
5703 }
5704
Willy Tarreau540abe42007-05-02 20:50:16 +02005705 /* zero out remaining args and ensure that at least one entry
5706 * is zeroed out.
5707 */
5708 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 args[arg] = line;
5710 }
5711
Willy Tarreau3842f002009-06-14 11:39:52 +02005712 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005713 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005714 char *tmp;
5715
Willy Tarreau3842f002009-06-14 11:39:52 +02005716 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005717 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005718 for (arg=0; *args[arg+1]; arg++)
5719 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005720 *tmp = '\0'; // fix the next arg to \0
5721 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005722 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005723 else if (!strcmp(args[0], "default")) {
5724 kwm = KWM_DEF;
5725 for (arg=0; *args[arg+1]; arg++)
5726 args[arg] = args[arg+1]; // shift args after inversion
5727 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005728
William Lallemand0f99e342011-10-12 17:50:54 +02005729 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5730 strcmp(args[0], "log") != 0) {
5731 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005732 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005733 }
5734
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005735 /* detect section start */
5736 list_for_each_entry(ics, &sections, list) {
5737 if (strcmp(args[0], ics->section_name) == 0) {
5738 cursection = ics->section_name;
5739 cs = ics;
5740 break;
5741 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005742 }
5743
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005745 if (cs)
5746 err_code |= cs->section_parser(file, linenum, args, kwm);
5747 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005748 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005749 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005751
5752 if (err_code & ERR_ABORT)
5753 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005755 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005757 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005758}
5759
Willy Tarreaubb925012009-07-23 13:36:36 +02005760/*
5761 * Returns the error code, 0 if OK, or any combination of :
5762 * - ERR_ABORT: must abort ASAP
5763 * - ERR_FATAL: we can continue parsing but not start the service
5764 * - ERR_WARN: a warning has been emitted
5765 * - ERR_ALERT: an alert has been emitted
5766 * Only the two first ones can stop processing, the two others are just
5767 * indicators.
5768 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005769int check_config_validity()
5770{
5771 int cfgerr = 0;
5772 struct proxy *curproxy = NULL;
5773 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005774 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005775 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005776 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005778 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005779 /*
5780 * Now, check for the integrity of all that we have collected.
5781 */
5782
5783 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005784 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785
Willy Tarreau193b8c62012-11-22 00:17:38 +01005786 if (!global.tune.max_http_hdr)
5787 global.tune.max_http_hdr = MAX_HTTP_HDR;
5788
5789 if (!global.tune.cookie_len)
5790 global.tune.cookie_len = CAPTURE_LEN;
5791
5792 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5793
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005794 /* Post initialisation of the users and groups lists. */
5795 err_code = userlist_postinit();
5796 if (err_code != ERR_NONE)
5797 goto out;
5798
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005799 /* first, we will invert the proxy list order */
5800 curproxy = NULL;
5801 while (proxy) {
5802 struct proxy *next;
5803
5804 next = proxy->next;
5805 proxy->next = curproxy;
5806 curproxy = proxy;
5807 if (!next)
5808 break;
5809 proxy = next;
5810 }
5811
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005813 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005814 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005815 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005816 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005817 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005818 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005819 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005820
Willy Tarreau050536d2012-10-04 08:47:34 +02005821 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005822 /* proxy ID not set, use automatic numbering with first
5823 * spare entry starting with next_pxid.
5824 */
5825 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5826 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5827 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005828 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005829 next_pxid++;
5830
Willy Tarreau55ea7572007-06-17 19:56:27 +02005831
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005833 /* ensure we don't keep listeners uselessly bound */
5834 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 curproxy = curproxy->next;
5836 continue;
5837 }
5838
Willy Tarreau16a21472012-11-19 12:39:59 +01005839 /* number of processes this proxy is bound to */
5840 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5841
Willy Tarreauff01a212009-03-15 13:46:16 +01005842 switch (curproxy->mode) {
5843 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005844 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005845 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005846 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5847 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005848 cfgerr++;
5849 }
5850
5851 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005852 Warning("config : servers will be ignored for %s '%s'.\n",
5853 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005854 break;
5855
5856 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005857 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005858 break;
5859
5860 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005861 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005862 break;
5863 }
5864
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005865 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005866 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005867 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005868 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5869 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005870 cfgerr++;
5871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005873 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005874 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5875 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005876 cfgerr++;
5877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005879 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005880 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5881 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005882 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005883 }
5884 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005885 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005886 /* If no LB algo is set in a backend, and we're not in
5887 * transparent mode, dispatch mode nor proxy mode, we
5888 * want to use balance roundrobin by default.
5889 */
5890 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5891 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 }
5893 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005894
Willy Tarreau1620ec32011-08-06 17:05:02 +02005895 if (curproxy->options & PR_O_DISPATCH)
5896 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5897 else if (curproxy->options & PR_O_HTTP_PROXY)
5898 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5899 else if (curproxy->options & PR_O_TRANSP)
5900 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005901
Willy Tarreau1620ec32011-08-06 17:05:02 +02005902 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5903 if (curproxy->options & PR_O_DISABLE404) {
5904 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5905 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5906 err_code |= ERR_WARN;
5907 curproxy->options &= ~PR_O_DISABLE404;
5908 }
5909 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5910 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5911 "send-state", proxy_type_str(curproxy), curproxy->id);
5912 err_code |= ERR_WARN;
5913 curproxy->options &= ~PR_O2_CHK_SNDST;
5914 }
Willy Tarreauef781042010-01-27 11:53:01 +01005915 }
5916
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005917 /* if a default backend was specified, let's find it */
5918 if (curproxy->defbe.name) {
5919 struct proxy *target;
5920
Alex Williams96532db2009-11-01 21:27:13 -05005921 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005922 if (!target) {
5923 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5924 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005925 cfgerr++;
5926 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005927 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5928 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005929 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005930 } else {
5931 free(curproxy->defbe.name);
5932 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005933 /* we force the backend to be present on at least all of
5934 * the frontend's processes.
5935 */
5936 target->bind_proc = curproxy->bind_proc ?
5937 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005938
5939 /* Emit a warning if this proxy also has some servers */
5940 if (curproxy->srv) {
5941 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5942 curproxy->id);
5943 err_code |= ERR_WARN;
5944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 }
5946 }
5947
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005948 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005949 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5950 /* map jump target for ACT_SETBE in req_rep chain */
5951 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005952 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005953 struct proxy *target;
5954
Willy Tarreaua496b602006-12-17 23:15:24 +01005955 if (exp->action != ACT_SETBE)
5956 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005957
Alex Williams96532db2009-11-01 21:27:13 -05005958 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005959 if (!target) {
5960 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5961 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005962 cfgerr++;
5963 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005964 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5965 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005966 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005967 } else {
5968 free((void *)exp->replace);
5969 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005970 /* we force the backend to be present on at least all of
5971 * the frontend's processes.
5972 */
5973 target->bind_proc = curproxy->bind_proc ?
5974 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005975 }
5976 }
5977 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005978
5979 /* find the target proxy for 'use_backend' rules */
5980 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005981 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005982 struct logformat_node *node;
5983 char *pxname;
5984
5985 /* Try to parse the string as a log format expression. If the result
5986 * of the parsing is only one entry containing a simple string, then
5987 * it's a standard string corresponding to a static rule, thus the
5988 * parsing is cancelled and be.name is restored to be resolved.
5989 */
5990 pxname = rule->be.name;
5991 LIST_INIT(&rule->be.expr);
5992 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5993 curproxy->conf.args.file, curproxy->conf.args.line);
5994 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5995
5996 if (!LIST_ISEMPTY(&rule->be.expr)) {
5997 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5998 rule->dynamic = 1;
5999 free(pxname);
6000 continue;
6001 }
6002 /* simple string: free the expression and fall back to static rule */
6003 free(node->arg);
6004 free(node);
6005 }
6006
6007 rule->dynamic = 0;
6008 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006009
Alex Williams96532db2009-11-01 21:27:13 -05006010 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006011
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006012 if (!target) {
6013 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6014 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006015 cfgerr++;
6016 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006017 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6018 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006019 cfgerr++;
6020 } else {
6021 free((void *)rule->be.name);
6022 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006023 /* we force the backend to be present on at least all of
6024 * the frontend's processes.
6025 */
6026 target->bind_proc = curproxy->bind_proc ?
6027 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006028 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006029 }
6030
6031 /* find the target proxy for 'use_backend' rules */
6032 list_for_each_entry(srule, &curproxy->server_rules, list) {
6033 struct server *target = findserver(curproxy, srule->srv.name);
6034
6035 if (!target) {
6036 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6037 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6038 cfgerr++;
6039 continue;
6040 }
6041 free((void *)srule->srv.name);
6042 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006043 }
6044
Emeric Brunb982a3d2010-01-04 15:45:53 +01006045 /* find the target table for 'stick' rules */
6046 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6047 struct proxy *target;
6048
Emeric Brun1d33b292010-01-04 15:47:17 +01006049 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6050 if (mrule->flags & STK_IS_STORE)
6051 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6052
Emeric Brunb982a3d2010-01-04 15:45:53 +01006053 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006054 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006055 else
6056 target = curproxy;
6057
6058 if (!target) {
6059 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6060 curproxy->id, mrule->table.name);
6061 cfgerr++;
6062 }
6063 else if (target->table.size == 0) {
6064 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6065 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6066 cfgerr++;
6067 }
Willy Tarreau12785782012-04-27 21:37:17 +02006068 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6069 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006070 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6071 cfgerr++;
6072 }
6073 else {
6074 free((void *)mrule->table.name);
6075 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006076 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006077 }
6078 }
6079
6080 /* find the target table for 'store response' rules */
6081 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6082 struct proxy *target;
6083
Emeric Brun1d33b292010-01-04 15:47:17 +01006084 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6085
Emeric Brunb982a3d2010-01-04 15:45:53 +01006086 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006087 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006088 else
6089 target = curproxy;
6090
6091 if (!target) {
6092 Alert("Proxy '%s': unable to find store table '%s'.\n",
6093 curproxy->id, mrule->table.name);
6094 cfgerr++;
6095 }
6096 else if (target->table.size == 0) {
6097 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6098 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6099 cfgerr++;
6100 }
Willy Tarreau12785782012-04-27 21:37:17 +02006101 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6102 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006103 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6104 cfgerr++;
6105 }
6106 else {
6107 free((void *)mrule->table.name);
6108 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006109 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006110 }
6111 }
6112
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006113 /* find the target table for 'tcp-request' layer 4 rules */
6114 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6115 struct proxy *target;
6116
Willy Tarreaub4c84932013-07-23 19:15:30 +02006117 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006118 continue;
6119
6120 if (trule->act_prm.trk_ctr.table.n)
6121 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6122 else
6123 target = curproxy;
6124
6125 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006126 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6127 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006128 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006129 cfgerr++;
6130 }
6131 else if (target->table.size == 0) {
6132 Alert("Proxy '%s': table '%s' used but not configured.\n",
6133 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6134 cfgerr++;
6135 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006136 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6137 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6138 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 +01006139 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006140 cfgerr++;
6141 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006142 else {
6143 free(trule->act_prm.trk_ctr.table.n);
6144 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006145 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006146 * to pass a list of counters to track and allocate them right here using
6147 * stktable_alloc_data_type().
6148 */
6149 }
6150 }
6151
Willy Tarreaud1f96522010-08-03 19:34:32 +02006152 /* find the target table for 'tcp-request' layer 6 rules */
6153 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6154 struct proxy *target;
6155
Willy Tarreaub4c84932013-07-23 19:15:30 +02006156 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006157 continue;
6158
6159 if (trule->act_prm.trk_ctr.table.n)
6160 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6161 else
6162 target = curproxy;
6163
6164 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006165 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6166 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006167 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006168 cfgerr++;
6169 }
6170 else if (target->table.size == 0) {
6171 Alert("Proxy '%s': table '%s' used but not configured.\n",
6172 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6173 cfgerr++;
6174 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006175 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6176 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6177 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 +01006178 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006179 cfgerr++;
6180 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006181 else {
6182 free(trule->act_prm.trk_ctr.table.n);
6183 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006184 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006185 * to pass a list of counters to track and allocate them right here using
6186 * stktable_alloc_data_type().
6187 */
6188 }
6189 }
6190
Emeric Brun32da3c42010-09-23 18:39:19 +02006191 if (curproxy->table.peers.name) {
6192 struct peers *curpeers = peers;
6193
6194 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6195 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6196 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006197 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006198 break;
6199 }
6200 }
6201
6202 if (!curpeers) {
6203 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6204 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006205 free((void *)curproxy->table.peers.name);
6206 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006207 cfgerr++;
6208 }
6209 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006210 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6211 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006212 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006213 cfgerr++;
6214 }
6215 }
6216
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006217 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006218 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006219 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6220 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6221 "proxy", curproxy->id);
6222 cfgerr++;
6223 goto out_uri_auth_compat;
6224 }
6225
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006226 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006227 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006228 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006229 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006230
Willy Tarreau95fa4692010-02-01 13:05:50 +01006231 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6232 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006233
6234 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006235 uri_auth_compat_req[i++] = "realm";
6236 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6237 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006238
Willy Tarreau95fa4692010-02-01 13:05:50 +01006239 uri_auth_compat_req[i++] = "unless";
6240 uri_auth_compat_req[i++] = "{";
6241 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6242 uri_auth_compat_req[i++] = "}";
6243 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006244
Willy Tarreauff011f22011-01-06 17:51:27 +01006245 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6246 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006247 cfgerr++;
6248 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006249 }
6250
Willy Tarreauff011f22011-01-06 17:51:27 +01006251 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006252
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006253 if (curproxy->uri_auth->auth_realm) {
6254 free(curproxy->uri_auth->auth_realm);
6255 curproxy->uri_auth->auth_realm = NULL;
6256 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006257
6258 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006259 }
6260out_uri_auth_compat:
6261
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006262 /* compile the log format */
6263 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006264 if (curproxy->conf.logformat_string != default_http_log_format &&
6265 curproxy->conf.logformat_string != default_tcp_log_format &&
6266 curproxy->conf.logformat_string != clf_http_log_format)
6267 free(curproxy->conf.logformat_string);
6268 curproxy->conf.logformat_string = NULL;
6269 free(curproxy->conf.lfs_file);
6270 curproxy->conf.lfs_file = NULL;
6271 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006272 }
6273
Willy Tarreau62a61232013-04-12 18:13:46 +02006274 if (curproxy->conf.logformat_string) {
6275 curproxy->conf.args.ctx = ARGC_LOG;
6276 curproxy->conf.args.file = curproxy->conf.lfs_file;
6277 curproxy->conf.args.line = curproxy->conf.lfs_line;
6278 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006279 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006280 curproxy->conf.args.file = NULL;
6281 curproxy->conf.args.line = 0;
6282 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006283
Willy Tarreau62a61232013-04-12 18:13:46 +02006284 if (curproxy->conf.uniqueid_format_string) {
6285 curproxy->conf.args.ctx = ARGC_UIF;
6286 curproxy->conf.args.file = curproxy->conf.uif_file;
6287 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006288 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006289 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6290 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006291 curproxy->conf.args.file = NULL;
6292 curproxy->conf.args.line = 0;
6293 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006294
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006295 /* only now we can check if some args remain unresolved.
6296 * This must be done after the users and groups resolution.
6297 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006298 cfgerr += smp_resolve_args(curproxy);
6299 if (!cfgerr)
6300 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006301
Willy Tarreau2738a142006-07-08 17:28:09 +02006302 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006303 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006304 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006305 (!curproxy->timeout.connect ||
6306 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006307 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006308 " | While not properly invalid, you will certainly encounter various problems\n"
6309 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006310 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006311 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006312 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006313 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006314
Willy Tarreau1fa31262007-12-03 00:36:16 +01006315 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6316 * We must still support older configurations, so let's find out whether those
6317 * parameters have been set or must be copied from contimeouts.
6318 */
6319 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006320 if (!curproxy->timeout.tarpit ||
6321 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006322 /* tarpit timeout not set. We search in the following order:
6323 * default.tarpit, curr.connect, default.connect.
6324 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006325 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006326 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006327 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006328 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006329 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006330 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006331 }
6332 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006333 (!curproxy->timeout.queue ||
6334 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006335 /* queue timeout not set. We search in the following order:
6336 * default.queue, curr.connect, default.connect.
6337 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006338 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006339 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006340 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006341 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006342 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006343 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006344 }
6345 }
6346
Willy Tarreau1620ec32011-08-06 17:05:02 +02006347 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006348 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6349 curproxy->check_req = (char *)malloc(curproxy->check_len);
6350 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006351 }
6352
Willy Tarreau193b8c62012-11-22 00:17:38 +01006353 /* ensure that cookie capture length is not too large */
6354 if (curproxy->capture_len >= global.tune.cookie_len) {
6355 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6356 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6357 err_code |= ERR_WARN;
6358 curproxy->capture_len = global.tune.cookie_len - 1;
6359 }
6360
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006361 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006362 if (curproxy->nb_req_cap) {
6363 if (curproxy->mode == PR_MODE_HTTP) {
6364 curproxy->req_cap_pool = create_pool("ptrcap",
6365 curproxy->nb_req_cap * sizeof(char *),
6366 MEM_F_SHARED);
6367 } else {
6368 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6369 proxy_type_str(curproxy), curproxy->id);
6370 err_code |= ERR_WARN;
6371 curproxy->to_log &= ~LW_REQHDR;
6372 curproxy->nb_req_cap = 0;
6373 }
6374 }
6375
6376 if (curproxy->nb_rsp_cap) {
6377 if (curproxy->mode == PR_MODE_HTTP) {
6378 curproxy->rsp_cap_pool = create_pool("ptrcap",
6379 curproxy->nb_rsp_cap * sizeof(char *),
6380 MEM_F_SHARED);
6381 } else {
6382 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6383 proxy_type_str(curproxy), curproxy->id);
6384 err_code |= ERR_WARN;
6385 curproxy->to_log &= ~LW_REQHDR;
6386 curproxy->nb_rsp_cap = 0;
6387 }
6388 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006389
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 /* first, we will invert the servers list order */
6391 newsrv = NULL;
6392 while (curproxy->srv) {
6393 struct server *next;
6394
6395 next = curproxy->srv->next;
6396 curproxy->srv->next = newsrv;
6397 newsrv = curproxy->srv;
6398 if (!next)
6399 break;
6400 curproxy->srv = next;
6401 }
6402
Willy Tarreau17edc812014-01-03 12:14:34 +01006403 /* Check that no server name conflicts. This causes trouble in the stats.
6404 * We only emit a warning for the first conflict affecting each server,
6405 * in order to avoid combinatory explosion if all servers have the same
6406 * name. We do that only for servers which do not have an explicit ID,
6407 * because these IDs were made also for distinguishing them and we don't
6408 * want to annoy people who correctly manage them.
6409 */
6410 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6411 struct server *other_srv;
6412
6413 if (newsrv->puid)
6414 continue;
6415
6416 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6417 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6418 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6419 newsrv->conf.file, newsrv->conf.line,
6420 proxy_type_str(curproxy), curproxy->id,
6421 newsrv->id, other_srv->conf.line);
6422 break;
6423 }
6424 }
6425 }
6426
Willy Tarreaudd701652010-05-25 23:03:02 +02006427 /* assign automatic UIDs to servers which don't have one yet */
6428 next_id = 1;
6429 newsrv = curproxy->srv;
6430 while (newsrv != NULL) {
6431 if (!newsrv->puid) {
6432 /* server ID not set, use automatic numbering with first
6433 * spare entry starting with next_svid.
6434 */
6435 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6436 newsrv->conf.id.key = newsrv->puid = next_id;
6437 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6438 }
6439 next_id++;
6440 newsrv = newsrv->next;
6441 }
6442
Willy Tarreau20697042007-11-15 23:26:18 +01006443 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006444 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445
Willy Tarreau62c3be22012-01-20 13:12:32 +01006446 /*
6447 * If this server supports a maxconn parameter, it needs a dedicated
6448 * tasks to fill the emptied slots when a connection leaves.
6449 * Also, resolve deferred tracking dependency if needed.
6450 */
6451 newsrv = curproxy->srv;
6452 while (newsrv != NULL) {
6453 if (newsrv->minconn > newsrv->maxconn) {
6454 /* Only 'minconn' was specified, or it was higher than or equal
6455 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6456 * this will avoid further useless expensive computations.
6457 */
6458 newsrv->maxconn = newsrv->minconn;
6459 } else if (newsrv->maxconn && !newsrv->minconn) {
6460 /* minconn was not specified, so we set it to maxconn */
6461 newsrv->minconn = newsrv->maxconn;
6462 }
6463
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006464#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006465 if (newsrv->use_ssl || newsrv->check.use_ssl)
6466 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006467#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006468
Willy Tarreau2f075e92013-12-03 11:11:34 +01006469 /* set the check type on the server */
6470 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6471
Willy Tarreau62c3be22012-01-20 13:12:32 +01006472 if (newsrv->trackit) {
6473 struct proxy *px;
6474 struct server *srv;
6475 char *pname, *sname;
6476
6477 pname = newsrv->trackit;
6478 sname = strrchr(pname, '/');
6479
6480 if (sname)
6481 *sname++ = '\0';
6482 else {
6483 sname = pname;
6484 pname = NULL;
6485 }
6486
6487 if (pname) {
6488 px = findproxy(pname, PR_CAP_BE);
6489 if (!px) {
6490 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6491 proxy_type_str(curproxy), curproxy->id,
6492 newsrv->id, pname);
6493 cfgerr++;
6494 goto next_srv;
6495 }
6496 } else
6497 px = curproxy;
6498
6499 srv = findserver(px, sname);
6500 if (!srv) {
6501 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6502 proxy_type_str(curproxy), curproxy->id,
6503 newsrv->id, sname);
6504 cfgerr++;
6505 goto next_srv;
6506 }
6507
Willy Tarreauff5ae352013-12-11 20:36:34 +01006508 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006509 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6510 "tracking as it does not have checks enabled.\n",
6511 proxy_type_str(curproxy), curproxy->id,
6512 newsrv->id, px->id, srv->id);
6513 cfgerr++;
6514 goto next_srv;
6515 }
6516
6517 if (curproxy != px &&
6518 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6519 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6520 "tracking: disable-on-404 option inconsistency.\n",
6521 proxy_type_str(curproxy), curproxy->id,
6522 newsrv->id, px->id, srv->id);
6523 cfgerr++;
6524 goto next_srv;
6525 }
6526
6527 /* if the other server is forced disabled, we have to do the same here */
6528 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006529 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006530 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006531 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006532 }
6533
6534 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006535 newsrv->tracknext = srv->trackers;
6536 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006537
6538 free(newsrv->trackit);
6539 newsrv->trackit = NULL;
6540 }
6541 next_srv:
6542 newsrv = newsrv->next;
6543 }
6544
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006545 /* We have to initialize the server lookup mechanism depending
6546 * on what LB algorithm was choosen.
6547 */
6548
6549 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6550 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6551 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006552 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6553 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6554 init_server_map(curproxy);
6555 } else {
6556 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6557 fwrr_init_server_groups(curproxy);
6558 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006559 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006560
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006561 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006562 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6563 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6564 fwlc_init_server_tree(curproxy);
6565 } else {
6566 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6567 fas_init_server_tree(curproxy);
6568 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006569 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006570
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006571 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006572 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6573 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6574 chash_init_server_tree(curproxy);
6575 } else {
6576 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6577 init_server_map(curproxy);
6578 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006579 break;
6580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581
6582 if (curproxy->options & PR_O_LOGASAP)
6583 curproxy->to_log &= ~LW_BYTES;
6584
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006585 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006586 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006587 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6588 proxy_type_str(curproxy), curproxy->id);
6589 err_code |= ERR_WARN;
6590 }
6591
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006592 if (curproxy->mode != PR_MODE_HTTP) {
6593 int optnum;
6594
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006595 if (curproxy->uri_auth) {
6596 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6597 proxy_type_str(curproxy), curproxy->id);
6598 err_code |= ERR_WARN;
6599 curproxy->uri_auth = NULL;
6600 }
6601
Willy Tarreau87cf5142011-08-19 22:57:24 +02006602 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006603 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6604 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6605 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006606 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006607 }
6608
6609 if (curproxy->options & PR_O_ORGTO) {
6610 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6611 "originalto", proxy_type_str(curproxy), curproxy->id);
6612 err_code |= ERR_WARN;
6613 curproxy->options &= ~PR_O_ORGTO;
6614 }
6615
6616 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6617 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6618 (curproxy->cap & cfg_opts[optnum].cap) &&
6619 (curproxy->options & cfg_opts[optnum].val)) {
6620 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6621 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6622 err_code |= ERR_WARN;
6623 curproxy->options &= ~cfg_opts[optnum].val;
6624 }
6625 }
6626
6627 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6628 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6629 (curproxy->cap & cfg_opts2[optnum].cap) &&
6630 (curproxy->options2 & cfg_opts2[optnum].val)) {
6631 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6632 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6633 err_code |= ERR_WARN;
6634 curproxy->options2 &= ~cfg_opts2[optnum].val;
6635 }
6636 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006637
Pieter Baauwd551fb52013-05-08 22:49:23 +02006638#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006639 if (curproxy->conn_src.bind_hdr_occ) {
6640 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006641 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006642 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006643 err_code |= ERR_WARN;
6644 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006645#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006646 }
6647
Willy Tarreaubaaee002006-06-26 02:48:02 +02006648 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006649 * ensure that we're not cross-dressing a TCP server into HTTP.
6650 */
6651 newsrv = curproxy->srv;
6652 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006653 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006654 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6655 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006656 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006657 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006658
Willy Tarreau0cec3312011-10-31 13:49:26 +01006659 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6660 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6661 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6662 err_code |= ERR_WARN;
6663 }
6664
Willy Tarreau82ffa392013-08-13 17:19:08 +02006665 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6666 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6667 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6668 err_code |= ERR_WARN;
6669 }
6670
Pieter Baauwd551fb52013-05-08 22:49:23 +02006671#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006672 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6673 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006674 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 +01006675 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006676 err_code |= ERR_WARN;
6677 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006678#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006679 newsrv = newsrv->next;
6680 }
6681
Willy Tarreauc1a21672009-08-16 22:37:44 +02006682 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006683 if (!curproxy->accept)
6684 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006685
Willy Tarreauc1a21672009-08-16 22:37:44 +02006686 if (curproxy->tcp_req.inspect_delay ||
6687 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006688 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006689
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006690 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006691 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006692 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006693 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006694
6695 /* both TCP and HTTP must check switching rules */
6696 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6697 }
6698
6699 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006700 if (curproxy->tcp_req.inspect_delay ||
6701 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6702 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6703
Emeric Brun97679e72010-09-23 17:56:44 +02006704 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6705 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6706
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006707 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006708 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006709 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006710 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006711
6712 /* If the backend does requires RDP cookie persistence, we have to
6713 * enable the corresponding analyser.
6714 */
6715 if (curproxy->options2 & PR_O2_RDPC_PRST)
6716 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6717 }
6718
Emeric Brunc52962f2012-11-15 18:28:02 +01006719#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006720 /* Configure SSL for each bind line.
6721 * Note: if configuration fails at some point, the ->ctx member
6722 * remains NULL so that listeners can later detach.
6723 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006724 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006725 if (!bind_conf->is_ssl) {
6726 if (bind_conf->default_ctx) {
6727 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6728 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6729 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006730 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006731 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006732 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006733 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006734 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006735 cfgerr++;
6736 continue;
6737 }
6738
Emeric Brun4b3091e2012-09-24 15:48:52 +02006739 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006740 Alert("Unable to allocate SSL session cache.\n");
6741 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006742 continue;
6743 }
6744
Emeric Brunfc0421f2012-09-07 17:30:07 +02006745 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006746 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006747 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006748#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006749
Willy Tarreaue6b98942007-10-29 01:09:36 +01006750 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006751 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006752 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006753 if (!listener->luid) {
6754 /* listener ID not set, use automatic numbering with first
6755 * spare entry starting with next_luid.
6756 */
6757 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6758 listener->conf.id.key = listener->luid = next_id;
6759 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006760 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006761 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006762
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006763 /* enable separate counters */
6764 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6765 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006766 if (!listener->name)
6767 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006768 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006769
Willy Tarreaue6b98942007-10-29 01:09:36 +01006770 if (curproxy->options & PR_O_TCP_NOLING)
6771 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006772 if (!listener->maxconn)
6773 listener->maxconn = curproxy->maxconn;
6774 if (!listener->backlog)
6775 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006776 if (!listener->maxaccept)
6777 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6778
6779 /* we want to have an optimal behaviour on single process mode to
6780 * maximize the work at once, but in multi-process we want to keep
6781 * some fairness between processes, so we target half of the max
6782 * number of events to be balanced over all the processes the proxy
6783 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6784 * used to disable the limit.
6785 */
6786 if (listener->maxaccept > 0) {
6787 if (nbproc > 1)
6788 listener->maxaccept = (listener->maxaccept + 1) / 2;
6789 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6790 }
6791
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006792 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006793 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006794 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006795 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006796
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006797 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6798 listener->options |= LI_O_TCP_RULES;
6799
Willy Tarreaude3041d2010-05-31 10:56:17 +02006800 if (curproxy->mon_mask.s_addr)
6801 listener->options |= LI_O_CHK_MONNET;
6802
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006803 /* smart accept mode is automatic in HTTP mode */
6804 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006805 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006806 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6807 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006808 }
6809
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006810 /* Release unused SSL configs */
6811 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6812 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006813 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006814#ifdef USE_OPENSSL
6815 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006816 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006817 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006818 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006819 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006820#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006821 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006822
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006823 /* Check multi-process mode compatibility for the current proxy */
6824 if (global.nbproc > 1) {
6825 int nbproc = 0;
6826 if (curproxy->bind_proc) {
6827 int proc;
6828 for (proc = 0; proc < global.nbproc; proc++) {
6829 if (curproxy->bind_proc & (1 << proc)) {
6830 nbproc++;
6831 }
6832 }
6833 } else {
6834 nbproc = global.nbproc;
6835 }
6836 if (curproxy->table.peers.name) {
6837 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6838 curproxy->id);
6839 cfgerr++;
6840 }
6841 if (nbproc > 1) {
6842 if (curproxy->uri_auth) {
6843 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6844 curproxy->id);
6845 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6846 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6847 curproxy->id);
6848 }
6849 }
6850 if (curproxy->appsession_name) {
6851 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6852 curproxy->id);
6853 }
6854 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6855 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6856 curproxy->id);
6857 }
6858 }
6859 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006860
6861 /* create the task associated with the proxy */
6862 curproxy->task = task_new();
6863 if (curproxy->task) {
6864 curproxy->task->context = curproxy;
6865 curproxy->task->process = manage_proxy;
6866 /* no need to queue, it will be done automatically if some
6867 * listener gets limited.
6868 */
6869 curproxy->task->expire = TICK_ETERNITY;
6870 } else {
6871 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6872 curproxy->id);
6873 cfgerr++;
6874 }
6875
Willy Tarreaubaaee002006-06-26 02:48:02 +02006876 curproxy = curproxy->next;
6877 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006878
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006879 /* Check multi-process mode compatibility */
6880 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006881 if (global.stats_fe && !global.stats_fe->bind_proc) {
6882 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006883 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006884 }
6885
6886 /* automatically compute fullconn if not set. We must not do it in the
6887 * loop above because cross-references are not yet fully resolved.
6888 */
6889 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6890 /* If <fullconn> is not set, let's set it to 10% of the sum of
6891 * the possible incoming frontend's maxconns.
6892 */
6893 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6894 struct proxy *fe;
6895 int total = 0;
6896
6897 /* sum up the number of maxconns of frontends which
6898 * reference this backend at least once or which are
6899 * the same one ('listen').
6900 */
6901 for (fe = proxy; fe; fe = fe->next) {
6902 struct switching_rule *rule;
6903 struct hdr_exp *exp;
6904 int found = 0;
6905
6906 if (!(fe->cap & PR_CAP_FE))
6907 continue;
6908
6909 if (fe == curproxy) /* we're on a "listen" instance */
6910 found = 1;
6911
6912 if (fe->defbe.be == curproxy) /* "default_backend" */
6913 found = 1;
6914
6915 /* check if a "use_backend" rule matches */
6916 if (!found) {
6917 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006918 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006919 found = 1;
6920 break;
6921 }
6922 }
6923 }
6924
6925 /* check if a "reqsetbe" rule matches */
6926 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6927 if (exp->action == ACT_SETBE &&
6928 (struct proxy *)exp->replace == curproxy) {
6929 found = 1;
6930 break;
6931 }
6932 }
6933
6934 /* now we've checked all possible ways to reference a backend
6935 * from a frontend.
6936 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006937 if (!found)
6938 continue;
6939 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006940 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006941 /* we have the sum of the maxconns in <total>. We only
6942 * keep 10% of that sum to set the default fullconn, with
6943 * a hard minimum of 1 (to avoid a divide by zero).
6944 */
6945 curproxy->fullconn = (total + 9) / 10;
6946 if (!curproxy->fullconn)
6947 curproxy->fullconn = 1;
6948 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006949 }
6950
Willy Tarreau056f5682010-06-06 15:51:11 +02006951 /* initialize stick-tables on backend capable proxies. This must not
6952 * be done earlier because the data size may be discovered while parsing
6953 * other proxies.
6954 */
Godbach9703e662013-12-11 21:11:41 +08006955 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006956 if (curproxy->state == PR_STSTOPPED)
6957 continue;
6958
Godbach9703e662013-12-11 21:11:41 +08006959 if (!stktable_init(&curproxy->table)) {
6960 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6961 cfgerr++;
6962 }
6963 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006964
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006965 /*
6966 * Recount currently required checks.
6967 */
6968
6969 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6970 int optnum;
6971
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006972 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6973 if (curproxy->options & cfg_opts[optnum].val)
6974 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006975
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006976 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6977 if (curproxy->options2 & cfg_opts2[optnum].val)
6978 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006979 }
6980
Willy Tarreau122541c2011-09-07 21:24:49 +02006981 if (peers) {
6982 struct peers *curpeers = peers, **last;
6983 struct peer *p, *pb;
6984
6985 /* Remove all peers sections which don't have a valid listener.
6986 * This can happen when a peers section is never referenced and
6987 * does not contain a local peer.
6988 */
6989 last = &peers;
6990 while (*last) {
6991 curpeers = *last;
6992 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006993 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006994 last = &curpeers->next;
6995 continue;
6996 }
6997
6998 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6999 curpeers->id, localpeer);
7000
7001 p = curpeers->remote;
7002 while (p) {
7003 pb = p->next;
7004 free(p->id);
7005 free(p);
7006 p = pb;
7007 }
7008
7009 /* Destroy and unlink this curpeers section.
7010 * Note: curpeers is backed up into *last.
7011 */
7012 free(curpeers->id);
7013 curpeers = curpeers->next;
7014 free(*last);
7015 *last = curpeers;
7016 }
7017 }
7018
Willy Tarreau34eb6712011-10-24 18:15:04 +02007019 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007020 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007021 MEM_F_SHARED);
7022
Willy Tarreaubb925012009-07-23 13:36:36 +02007023 if (cfgerr > 0)
7024 err_code |= ERR_ALERT | ERR_FATAL;
7025 out:
7026 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007027}
7028
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007029/*
7030 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7031 * parsing sessions.
7032 */
7033void cfg_register_keywords(struct cfg_kw_list *kwl)
7034{
7035 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7036}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007038/*
7039 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7040 */
7041void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7042{
7043 LIST_DEL(&kwl->list);
7044 LIST_INIT(&kwl->list);
7045}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007046
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007047/* this function register new section in the haproxy configuration file.
7048 * <section_name> is the name of this new section and <section_parser>
7049 * is the called parser. If two section declaration have the same name,
7050 * only the first declared is used.
7051 */
7052int cfg_register_section(char *section_name,
7053 int (*section_parser)(const char *, int, char **, int))
7054{
7055 struct cfg_section *cs;
7056
7057 cs = calloc(1, sizeof(*cs));
7058 if (!cs) {
7059 Alert("register section '%s': out of memory.\n", section_name);
7060 return 0;
7061 }
7062
7063 cs->section_name = section_name;
7064 cs->section_parser = section_parser;
7065
7066 LIST_ADDQ(&sections, &cs->list);
7067
7068 return 1;
7069}
7070
Willy Tarreaubaaee002006-06-26 02:48:02 +02007071/*
7072 * Local variables:
7073 * c-indent-level: 8
7074 * c-basic-offset: 8
7075 * End:
7076 */