blob: 7a869e36c8eca16a83a91a2d462ef55742d13d11 [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 Tarreauc35362a2014-04-25 13:58:37 +02001933 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001935 if (defproxy.check_req) {
1936 curproxy->check_req = calloc(1, defproxy.check_len);
1937 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001941 if (defproxy.expect_str) {
1942 curproxy->expect_str = strdup(defproxy.expect_str);
1943 if (defproxy.expect_regex) {
1944 /* note: this regex is known to be valid */
1945 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1946 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1947 }
1948 }
1949
Willy Tarreau67402132012-05-31 20:40:20 +02001950 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (defproxy.cookie_name)
1952 curproxy->cookie_name = strdup(defproxy.cookie_name);
1953 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001954 if (defproxy.cookie_domain)
1955 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001956
Willy Tarreau31936852010-10-06 16:59:56 +02001957 if (defproxy.cookie_maxidle)
1958 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1959
1960 if (defproxy.cookie_maxlife)
1961 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1962
Emeric Brun647caf12009-06-30 17:57:00 +02001963 if (defproxy.rdp_cookie_name)
1964 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1965 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1966
Willy Tarreau01732802007-11-01 22:48:15 +01001967 if (defproxy.url_param_name)
1968 curproxy->url_param_name = strdup(defproxy.url_param_name);
1969 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001970
Benoitaffb4812009-03-25 13:02:10 +01001971 if (defproxy.hh_name)
1972 curproxy->hh_name = strdup(defproxy.hh_name);
1973 curproxy->hh_len = defproxy.hh_len;
1974 curproxy->hh_match_domain = defproxy.hh_match_domain;
1975
Willy Tarreauef9a3602012-12-08 22:29:20 +01001976 if (defproxy.conn_src.iface_name)
1977 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1978 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001979 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001980#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001981 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001982#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001985 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (defproxy.capture_name)
1987 curproxy->capture_name = strdup(defproxy.capture_name);
1988 curproxy->capture_namelen = defproxy.capture_namelen;
1989 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001993 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001994 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001995 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001996 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 curproxy->mon_net = defproxy.mon_net;
1998 curproxy->mon_mask = defproxy.mon_mask;
1999 if (defproxy.monitor_uri)
2000 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2001 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002002 if (defproxy.defbe.name)
2003 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002004
2005 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002006 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2007 if (curproxy->conf.logformat_string &&
2008 curproxy->conf.logformat_string != default_http_log_format &&
2009 curproxy->conf.logformat_string != default_tcp_log_format &&
2010 curproxy->conf.logformat_string != clf_http_log_format)
2011 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2012
2013 if (defproxy.conf.lfs_file) {
2014 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2015 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2016 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002017 }
2018
2019 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002020 curproxy->timeout.connect = defproxy.timeout.connect;
2021 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002022 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002023 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002024 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002025 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002026 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002027 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002028 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002029 }
2030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002032 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002033
2034 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002035 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002036 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002037 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002038 LIST_INIT(&node->list);
2039 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2040 }
2041
Willy Tarreau62a61232013-04-12 18:13:46 +02002042 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2043 if (curproxy->conf.uniqueid_format_string)
2044 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2045
2046 if (defproxy.conf.uif_file) {
2047 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2048 curproxy->conf.uif_line = defproxy.conf.uif_line;
2049 }
William Lallemanda73203e2012-03-12 12:48:57 +01002050
2051 /* copy default header unique id */
2052 if (defproxy.header_unique_id)
2053 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2054
William Lallemand82fe75c2012-10-23 10:25:10 +02002055 /* default compression options */
2056 if (defproxy.comp != NULL) {
2057 curproxy->comp = calloc(1, sizeof(struct comp));
2058 curproxy->comp->algos = defproxy.comp->algos;
2059 curproxy->comp->types = defproxy.comp->types;
2060 }
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002063 curproxy->conf.used_listener_id = EB_ROOT;
2064 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002065
Willy Tarreau93893792009-07-23 13:19:11 +02002066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 }
2068 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2069 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002070 /* FIXME-20070101: we should do this too at the end of the
2071 * config parsing to free all default values.
2072 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073 free(defproxy.check_req);
2074 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002075 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002076 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002077 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002078 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002079 free(defproxy.capture_name);
2080 free(defproxy.monitor_uri);
2081 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002082 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002083 free(defproxy.fwdfor_hdr_name);
2084 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002085 free(defproxy.orgto_hdr_name);
2086 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002087 free(defproxy.server_id_hdr_name);
2088 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002089 free(defproxy.expect_str);
2090 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002091
Willy Tarreau62a61232013-04-12 18:13:46 +02002092 if (defproxy.conf.logformat_string != default_http_log_format &&
2093 defproxy.conf.logformat_string != default_tcp_log_format &&
2094 defproxy.conf.logformat_string != clf_http_log_format)
2095 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002096
Willy Tarreau62a61232013-04-12 18:13:46 +02002097 free(defproxy.conf.uniqueid_format_string);
2098 free(defproxy.conf.lfs_file);
2099 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002100
Willy Tarreaua534fea2008-08-03 12:19:50 +02002101 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002102 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 /* we cannot free uri_auth because it might already be used */
2105 init_default_instance();
2106 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002107 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2108 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
2112 else if (curproxy == NULL) {
2113 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002117
2118 /* update the current file and line being parsed */
2119 curproxy->conf.args.file = curproxy->conf.file;
2120 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121
2122 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002123 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2124 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2125 if (err_code & ERR_FATAL)
2126 goto out;
2127 }
2128 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002129 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002130 int cur_arg;
2131
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 if (curproxy == &defproxy) {
2133 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139
Willy Tarreau24709282013-03-10 21:32:12 +01002140 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002141 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002146
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002147 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002148
2149 /* use default settings for unix sockets */
2150 bind_conf->ux.uid = global.unix_bind.ux.uid;
2151 bind_conf->ux.gid = global.unix_bind.ux.gid;
2152 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002153
2154 /* NOTE: the following line might create several listeners if there
2155 * are comma-separated IPs or port ranges. So all further processing
2156 * will have to be applied to all listeners created after last_listen.
2157 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002158 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2159 if (errmsg && *errmsg) {
2160 indent_msg(&errmsg, 2);
2161 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002162 }
2163 else
2164 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2165 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002169
Willy Tarreau4348fad2012-09-20 16:48:07 +02002170 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2171 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002172 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002173 }
2174
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002175 cur_arg = 2;
2176 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002177 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002178 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002179 char *err;
2180
Willy Tarreau26982662012-09-12 23:17:10 +02002181 kw = bind_find_kw(args[cur_arg]);
2182 if (kw) {
2183 char *err = NULL;
2184 int code;
2185
2186 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002187 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2188 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002189 cur_arg += 1 + kw->skip ;
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
Willy Tarreau4348fad2012-09-20 16:48:07 +02002194 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002195 err_code |= code;
2196
2197 if (code) {
2198 if (err && *err) {
2199 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002200 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002201 }
2202 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002203 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2204 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002205 if (code & ERR_FATAL) {
2206 free(err);
2207 cur_arg += 1 + kw->skip;
2208 goto out;
2209 }
2210 }
2211 free(err);
2212 cur_arg += 1 + kw->skip;
2213 continue;
2214 }
2215
Willy Tarreau8638f482012-09-18 18:01:17 +02002216 err = NULL;
2217 if (!bind_dumped) {
2218 bind_dump_kws(&err);
2219 indent_msg(&err, 4);
2220 bind_dumped = 1;
2221 }
2222
2223 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2224 file, linenum, args[0], args[1], args[cur_arg],
2225 err ? " Registered keywords :" : "", err ? err : "");
2226 free(err);
2227
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002230 }
Willy Tarreau93893792009-07-23 13:19:11 +02002231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
2233 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002234 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2236 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 /* flush useless bits */
2244 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002247 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002248 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
Willy Tarreau1c47f852006-07-09 08:22:27 +02002251 if (!*args[1]) {
2252 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002256 }
2257
Willy Tarreaua534fea2008-08-03 12:19:50 +02002258 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002259 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002260 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002261 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002262 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2263
Willy Tarreau93893792009-07-23 13:19:11 +02002264 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2267 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2268 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2269 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2270 else {
2271 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
2275 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002276 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002277 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002278
2279 if (curproxy == &defproxy) {
2280 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2281 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002284 }
2285
2286 if (!*args[1]) {
2287 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002291 }
2292
2293 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002294 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002295
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002296 if (curproxy->uuid <= 0) {
2297 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002298 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002301 }
2302
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002303 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2304 if (node) {
2305 struct proxy *target = container_of(node, struct proxy, conf.id);
2306 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2307 file, linenum, proxy_type_str(curproxy), curproxy->id,
2308 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002313 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002314 else if (!strcmp(args[0], "description")) {
2315 int i, len=0;
2316 char *d;
2317
Cyril Bonté99ed3272010-01-24 23:29:44 +01002318 if (curproxy == &defproxy) {
2319 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2320 file, linenum, args[0]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002325 if (!*args[1]) {
2326 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2327 file, linenum, args[0]);
2328 return -1;
2329 }
2330
Willy Tarreau348acfe2014-04-14 15:00:39 +02002331 for (i = 1; *args[i]; i++)
2332 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002333
2334 d = (char *)calloc(1, len);
2335 curproxy->desc = d;
2336
Willy Tarreau348acfe2014-04-14 15:00:39 +02002337 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2338 for (i = 2; *args[i]; i++)
2339 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002340
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2343 curproxy->state = PR_STSTOPPED;
2344 }
2345 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2346 curproxy->state = PR_STNEW;
2347 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002348 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2349 int cur_arg = 1;
2350 unsigned int set = 0;
2351
2352 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002353 unsigned int low, high;
2354
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002355 if (strcmp(args[cur_arg], "all") == 0) {
2356 set = 0;
2357 break;
2358 }
2359 else if (strcmp(args[cur_arg], "odd") == 0) {
2360 set |= 0x55555555;
2361 }
2362 else if (strcmp(args[cur_arg], "even") == 0) {
2363 set |= 0xAAAAAAAA;
2364 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002365 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002366 char *dash = strchr(args[cur_arg], '-');
2367
2368 low = high = str2uic(args[cur_arg]);
2369 if (dash)
2370 high = str2uic(dash + 1);
2371
2372 if (high < low) {
2373 unsigned int swap = low;
2374 low = high;
2375 high = swap;
2376 }
2377
2378 if (low < 1 || high > 32) {
2379 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002383 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002384
2385 if (high > global.nbproc) {
2386 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2387 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002389 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002390 while (low <= high)
2391 set |= 1 << (low++ - 1);
2392 }
2393 else {
2394 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2395 file, linenum, args[0]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002398 }
2399 cur_arg++;
2400 }
2401 curproxy->bind_proc = set;
2402 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002403 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002404 if (curproxy == &defproxy) {
2405 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002408 }
2409
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002410 err = invalid_char(args[1]);
2411 if (err) {
2412 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2413 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002415 }
2416
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002417 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002418 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2419 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002422 }
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2425 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 if (*(args[1]) == 0) {
2431 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002436
Willy Tarreau67402132012-05-31 20:40:20 +02002437 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002438 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002439 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002440 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 curproxy->cookie_name = strdup(args[1]);
2442 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002443
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 cur_arg = 2;
2445 while (*(args[cur_arg])) {
2446 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002447 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
2449 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002450 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002453 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
2455 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002456 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002459 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002461 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002462 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002465 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002467 else if (!strcmp(args[cur_arg], "httponly")) {
2468 curproxy->ck_opts |= PR_CK_HTTPONLY;
2469 }
2470 else if (!strcmp(args[cur_arg], "secure")) {
2471 curproxy->ck_opts |= PR_CK_SECURE;
2472 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002473 else if (!strcmp(args[cur_arg], "domain")) {
2474 if (!*args[cur_arg + 1]) {
2475 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2476 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002479 }
2480
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002481 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002482 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002483 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2484 " dots nor does not start with a dot."
2485 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002486 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002487 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002488 }
2489
2490 err = invalid_domainchar(args[cur_arg + 1]);
2491 if (err) {
2492 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2493 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002496 }
2497
Willy Tarreau68a897b2009-12-03 23:28:34 +01002498 if (!curproxy->cookie_domain) {
2499 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2500 } else {
2501 /* one domain was already specified, add another one by
2502 * building the string which will be returned along with
2503 * the cookie.
2504 */
2505 char *new_ptr;
2506 int new_len = strlen(curproxy->cookie_domain) +
2507 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2508 new_ptr = malloc(new_len);
2509 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2510 free(curproxy->cookie_domain);
2511 curproxy->cookie_domain = new_ptr;
2512 }
Willy Tarreau31936852010-10-06 16:59:56 +02002513 cur_arg++;
2514 }
2515 else if (!strcmp(args[cur_arg], "maxidle")) {
2516 unsigned int maxidle;
2517 const char *res;
2518
2519 if (!*args[cur_arg + 1]) {
2520 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2521 file, linenum, args[cur_arg]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
2526 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2527 if (res) {
2528 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2529 file, linenum, *res, args[cur_arg]);
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533 curproxy->cookie_maxidle = maxidle;
2534 cur_arg++;
2535 }
2536 else if (!strcmp(args[cur_arg], "maxlife")) {
2537 unsigned int maxlife;
2538 const char *res;
2539
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2542 file, linenum, args[cur_arg]);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546
2547 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2548 if (res) {
2549 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2550 file, linenum, *res, args[cur_arg]);
2551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
2553 }
2554 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002555 cur_arg++;
2556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002558 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 +02002559 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563 cur_arg++;
2564 }
Willy Tarreau67402132012-05-31 20:40:20 +02002565 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2567 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
Willy Tarreau67402132012-05-31 20:40:20 +02002571 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2573 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002576
Willy Tarreau67402132012-05-31 20:40:20 +02002577 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002578 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2579 file, linenum);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002583 else if (!strcmp(args[0], "persist")) { /* persist */
2584 if (*(args[1]) == 0) {
2585 Alert("parsing [%s:%d] : missing persist method.\n",
2586 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002589 }
2590
2591 if (!strncmp(args[1], "rdp-cookie", 10)) {
2592 curproxy->options2 |= PR_O2_RDPC_PRST;
2593
Emeric Brunb982a3d2010-01-04 15:45:53 +01002594 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002595 const char *beg, *end;
2596
2597 beg = args[1] + 11;
2598 end = strchr(beg, ')');
2599
2600 if (!end || end == beg) {
2601 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2602 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002605 }
2606
2607 free(curproxy->rdp_cookie_name);
2608 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2609 curproxy->rdp_cookie_len = end-beg;
2610 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002611 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002612 free(curproxy->rdp_cookie_name);
2613 curproxy->rdp_cookie_name = strdup("msts");
2614 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2615 }
2616 else { /* syntax */
2617 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2618 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002621 }
2622 }
2623 else {
2624 Alert("parsing [%s:%d] : unknown persist method.\n",
2625 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002628 }
2629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002631 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002633 if (curproxy == &defproxy) {
2634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002643 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
2648 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002649 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 curproxy->appsession_name = strdup(args[1]);
2651 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2652 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002653 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2654 if (err) {
2655 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2656 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002659 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002660 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002661
Willy Tarreau51041c72007-09-09 21:56:53 +02002662 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2663 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_ABORT;
2665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002667
2668 cur_arg = 6;
2669 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002670 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2671 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002672 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002673 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002674 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002675 } else if (!strcmp(args[cur_arg], "prefix")) {
2676 curproxy->options2 |= PR_O2_AS_PFX;
2677 } else if (!strcmp(args[cur_arg], "mode")) {
2678 if (!*args[cur_arg + 1]) {
2679 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2680 file, linenum, args[0], args[cur_arg]);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
2685 cur_arg++;
2686 if (!strcmp(args[cur_arg], "query-string")) {
2687 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2688 curproxy->options2 |= PR_O2_AS_M_QS;
2689 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2690 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2691 curproxy->options2 |= PR_O2_AS_M_PP;
2692 } else {
2693 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002698 cur_arg++;
2699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 } /* Url App Session */
2701 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002706 if (curproxy == &defproxy) {
2707 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 if (*(args[4]) == 0) {
2713 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002718 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 curproxy->capture_name = strdup(args[2]);
2720 curproxy->capture_namelen = strlen(curproxy->capture_name);
2721 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 curproxy->to_log |= LW_COOKIE;
2723 }
2724 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2725 struct cap_hdr *hdr;
2726
2727 if (curproxy == &defproxy) {
2728 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 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
2732
2733 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2734 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2735 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 }
2739
2740 hdr = calloc(sizeof(struct cap_hdr), 1);
2741 hdr->next = curproxy->req_cap;
2742 hdr->name = strdup(args[3]);
2743 hdr->namelen = strlen(args[3]);
2744 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002745 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 hdr->index = curproxy->nb_req_cap++;
2747 curproxy->req_cap = hdr;
2748 curproxy->to_log |= LW_REQHDR;
2749 }
2750 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2751 struct cap_hdr *hdr;
2752
2753 if (curproxy == &defproxy) {
2754 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 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758
2759 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2760 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2761 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 hdr = calloc(sizeof(struct cap_hdr), 1);
2766 hdr->next = curproxy->rsp_cap;
2767 hdr->name = strdup(args[3]);
2768 hdr->namelen = strlen(args[3]);
2769 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002770 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 hdr->index = curproxy->nb_rsp_cap++;
2772 curproxy->rsp_cap = hdr;
2773 curproxy->to_log |= LW_RSPHDR;
2774 }
2775 else {
2776 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2777 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002785
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 if (*(args[1]) == 0) {
2787 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 }
2792 curproxy->conn_retries = atol(args[1]);
2793 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002794 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002795 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002796
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
Willy Tarreau20b0de52012-12-24 15:45:22 +01002803 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2804 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2805 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2806 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002807 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002808 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2809 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 +01002810 file, linenum, args[0]);
2811 err_code |= ERR_WARN;
2812 }
2813
Willy Tarreauff011f22011-01-06 17:51:27 +01002814 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002815
Willy Tarreauff011f22011-01-06 17:51:27 +01002816 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002817 err_code |= ERR_ALERT | ERR_ABORT;
2818 goto out;
2819 }
2820
Willy Tarreau5002f572014-04-23 01:32:02 +02002821 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002822 err_code |= warnif_cond_conflicts(rule->cond,
2823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2824 file, linenum);
2825
Willy Tarreauff011f22011-01-06 17:51:27 +01002826 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002827 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002828 else if (!strcmp(args[0], "http-response")) { /* response access control */
2829 struct http_res_rule *rule;
2830
2831 if (curproxy == &defproxy) {
2832 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
2837 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2838 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2839 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2840 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2841 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2842 file, linenum, args[0]);
2843 err_code |= ERR_WARN;
2844 }
2845
2846 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2847
2848 if (!rule) {
2849 err_code |= ERR_ALERT | ERR_ABORT;
2850 goto out;
2851 }
2852
2853 err_code |= warnif_cond_conflicts(rule->cond,
2854 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2855 file, linenum);
2856
2857 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2858 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002859 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2860 /* set the header name and length into the proxy structure */
2861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2862 err_code |= ERR_WARN;
2863
2864 if (!*args[1]) {
2865 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2866 file, linenum, args[0]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870
2871 /* set the desired header name */
2872 free(curproxy->server_id_hdr_name);
2873 curproxy->server_id_hdr_name = strdup(args[1]);
2874 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2875 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002876 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002877 if (curproxy == &defproxy) {
2878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002881 }
2882
Willy Tarreauef6494c2010-01-28 17:12:36 +01002883 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002884 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2885 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002888 }
2889
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002890 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2891 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2892 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002895 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002896
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002897 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002898 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002899 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002900 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002901 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002902
Cyril Bonté99ed3272010-01-24 23:29:44 +01002903 if (curproxy == &defproxy) {
2904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002909 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002910 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2911 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002914 }
2915
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002916 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002917 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002918 err_code |= warnif_cond_conflicts(rule->cond,
2919 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2920 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002921 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002922 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002923 struct switching_rule *rule;
2924
Willy Tarreaub099aca2008-10-12 17:26:37 +02002925 if (curproxy == &defproxy) {
2926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002929 }
2930
Willy Tarreau55ea7572007-06-17 19:56:27 +02002931 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002933
2934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002938 }
2939
Willy Tarreauf51658d2014-04-23 01:21:56 +02002940 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2941 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2942 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2943 file, linenum, errmsg);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002947
Willy Tarreauf51658d2014-04-23 01:21:56 +02002948 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002949 }
2950
2951 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2952 rule->cond = cond;
2953 rule->be.name = strdup(args[1]);
2954 LIST_INIT(&rule->list);
2955 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2956 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002957 else if (strcmp(args[0], "use-server") == 0) {
2958 struct server_rule *rule;
2959
2960 if (curproxy == &defproxy) {
2961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2967 err_code |= ERR_WARN;
2968
2969 if (*(args[1]) == 0) {
2970 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974
2975 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2976 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2977 file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2983 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2984 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002989 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002990
2991 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2992 rule->cond = cond;
2993 rule->srv.name = strdup(args[1]);
2994 LIST_INIT(&rule->list);
2995 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2996 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2997 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002998 else if ((!strcmp(args[0], "force-persist")) ||
2999 (!strcmp(args[0], "ignore-persist"))) {
3000 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003001
3002 if (curproxy == &defproxy) {
3003 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3009 err_code |= ERR_WARN;
3010
Willy Tarreauef6494c2010-01-28 17:12:36 +01003011 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003012 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3013 file, linenum, args[0]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003018 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3019 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3020 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003025 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3026 * where force-persist is applied.
3027 */
3028 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003029
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003030 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003031 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003032 if (!strcmp(args[0], "force-persist")) {
3033 rule->type = PERSIST_TYPE_FORCE;
3034 } else {
3035 rule->type = PERSIST_TYPE_IGNORE;
3036 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003037 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003038 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003039 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 else if (!strcmp(args[0], "stick-table")) {
3041 int myidx = 1;
3042
Emeric Brun32da3c42010-09-23 18:39:19 +02003043 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 curproxy->table.type = (unsigned int)-1;
3045 while (*args[myidx]) {
3046 const char *err;
3047
3048 if (strcmp(args[myidx], "size") == 0) {
3049 myidx++;
3050 if (!*(args[myidx])) {
3051 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3052 file, linenum, args[myidx-1]);
3053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
3055 }
3056 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3057 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3058 file, linenum, *err, args[myidx-1]);
3059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
3061 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003062 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003063 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003064 else if (strcmp(args[myidx], "peers") == 0) {
3065 myidx++;
Godbach50523162013-12-11 19:48:57 +08003066 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003067 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3068 file, linenum, args[myidx-1]);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Godbach50523162013-12-11 19:48:57 +08003071 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003072 curproxy->table.peers.name = strdup(args[myidx++]);
3073 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003074 else if (strcmp(args[myidx], "expire") == 0) {
3075 myidx++;
3076 if (!*(args[myidx])) {
3077 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3078 file, linenum, args[myidx-1]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3083 if (err) {
3084 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3085 file, linenum, *err, args[myidx-1]);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003090 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003091 }
3092 else if (strcmp(args[myidx], "nopurge") == 0) {
3093 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003094 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003095 }
3096 else if (strcmp(args[myidx], "type") == 0) {
3097 myidx++;
3098 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3099 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3100 file, linenum, args[myidx]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003104 /* myidx already points to next arg */
3105 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003106 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003107 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003108 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003109
3110 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003111 nw = args[myidx];
3112 while (*nw) {
3113 /* the "store" keyword supports a comma-separated list */
3114 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003115 sa = NULL; /* store arg */
3116 while (*nw && *nw != ',') {
3117 if (*nw == '(') {
3118 *nw = 0;
3119 sa = ++nw;
3120 while (*nw != ')') {
3121 if (!*nw) {
3122 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3123 file, linenum, args[0], cw);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127 nw++;
3128 }
3129 *nw = '\0';
3130 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003131 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003132 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003133 if (*nw)
3134 *nw++ = '\0';
3135 type = stktable_get_data_type(cw);
3136 if (type < 0) {
3137 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3138 file, linenum, args[0], cw);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
Willy Tarreauac782882010-06-20 10:41:54 +02003142
3143 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3144 switch (err) {
3145 case PE_NONE: break;
3146 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003147 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3148 file, linenum, args[0], cw);
3149 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003150 break;
3151
3152 case PE_ARG_MISSING:
3153 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3154 file, linenum, args[0], cw);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157
3158 case PE_ARG_NOT_USED:
3159 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3160 file, linenum, args[0], cw);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163
3164 default:
3165 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3166 file, linenum, args[0], cw);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003169 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003170 }
3171 myidx++;
3172 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003173 else {
3174 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3175 file, linenum, args[myidx]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003179 }
3180
3181 if (!curproxy->table.size) {
3182 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3183 file, linenum);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186 }
3187
3188 if (curproxy->table.type == (unsigned int)-1) {
3189 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3190 file, linenum);
3191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
3193 }
3194 }
3195 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003197 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003198 int myidx = 0;
3199 const char *name = NULL;
3200 int flags;
3201
3202 if (curproxy == &defproxy) {
3203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
3208 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3209 err_code |= ERR_WARN;
3210 goto out;
3211 }
3212
3213 myidx++;
3214 if ((strcmp(args[myidx], "store") == 0) ||
3215 (strcmp(args[myidx], "store-request") == 0)) {
3216 myidx++;
3217 flags = STK_IS_STORE;
3218 }
3219 else if (strcmp(args[myidx], "store-response") == 0) {
3220 myidx++;
3221 flags = STK_IS_STORE | STK_ON_RSP;
3222 }
3223 else if (strcmp(args[myidx], "match") == 0) {
3224 myidx++;
3225 flags = STK_IS_MATCH;
3226 }
3227 else if (strcmp(args[myidx], "on") == 0) {
3228 myidx++;
3229 flags = STK_IS_MATCH | STK_IS_STORE;
3230 }
3231 else {
3232 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236
3237 if (*(args[myidx]) == 0) {
3238 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
3242
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003243 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003244 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003245 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003246 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250
3251 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003252 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3253 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3254 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003255 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003256 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003257 goto out;
3258 }
3259 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003260 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3261 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3262 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003264 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003265 goto out;
3266 }
3267 }
3268
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003269 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003270 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003271
Emeric Brunb982a3d2010-01-04 15:45:53 +01003272 if (strcmp(args[myidx], "table") == 0) {
3273 myidx++;
3274 name = args[myidx++];
3275 }
3276
Willy Tarreauef6494c2010-01-28 17:12:36 +01003277 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003278 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3279 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3280 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003281 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003282 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003283 goto out;
3284 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003285 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003286 else if (*(args[myidx])) {
3287 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3288 file, linenum, args[0], args[myidx]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003290 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003291 goto out;
3292 }
Emeric Brun97679e72010-09-23 17:56:44 +02003293 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003294 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003295 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003296 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003297
Emeric Brunb982a3d2010-01-04 15:45:53 +01003298 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3299 rule->cond = cond;
3300 rule->expr = expr;
3301 rule->flags = flags;
3302 rule->table.name = name ? strdup(name) : NULL;
3303 LIST_INIT(&rule->list);
3304 if (flags & STK_ON_RSP)
3305 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3306 else
3307 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 else if (!strcmp(args[0], "stats")) {
3310 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3311 curproxy->uri_auth = NULL; /* we must detach from the default config */
3312
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003313 if (!*args[1]) {
3314 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003315 } else if (!strcmp(args[1], "admin")) {
3316 struct stats_admin_rule *rule;
3317
3318 if (curproxy == &defproxy) {
3319 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
3323
3324 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3325 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
3328 }
3329
3330 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3331 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3332 file, linenum, args[0], args[1]);
3333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003336 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3337 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3338 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003343 err_code |= warnif_cond_conflicts(cond,
3344 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3345 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003346
3347 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3348 rule->cond = cond;
3349 LIST_INIT(&rule->list);
3350 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 } else if (!strcmp(args[1], "uri")) {
3352 if (*(args[2]) == 0) {
3353 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_ABORT;
3359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
3361 } else if (!strcmp(args[1], "realm")) {
3362 if (*(args[2]) == 0) {
3363 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_ABORT;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003371 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003372 unsigned interval;
3373
3374 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3375 if (err) {
3376 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3377 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003380 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_ABORT;
3383 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003384 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003385 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003386 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003387
3388 if (curproxy == &defproxy) {
3389 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393
3394 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3395 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3396 err_code |= ERR_ALERT | ERR_ABORT;
3397 goto out;
3398 }
3399
Willy Tarreauff011f22011-01-06 17:51:27 +01003400 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3401 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003402 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3403 file, linenum, args[0]);
3404 err_code |= ERR_WARN;
3405 }
3406
Willy Tarreauff011f22011-01-06 17:51:27 +01003407 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003408
Willy Tarreauff011f22011-01-06 17:51:27 +01003409 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003410 err_code |= ERR_ALERT | ERR_ABORT;
3411 goto out;
3412 }
3413
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003414 err_code |= warnif_cond_conflicts(rule->cond,
3415 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3416 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003417 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003418
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 } else if (!strcmp(args[1], "auth")) {
3420 if (*(args[2]) == 0) {
3421 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_ABORT;
3427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
3429 } else if (!strcmp(args[1], "scope")) {
3430 if (*(args[2]) == 0) {
3431 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3435 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_ABORT;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
3439 } else if (!strcmp(args[1], "enable")) {
3440 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3441 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_ABORT;
3443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003445 } else if (!strcmp(args[1], "hide-version")) {
3446 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3447 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003448 err_code |= ERR_ALERT | ERR_ABORT;
3449 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003450 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003451 } else if (!strcmp(args[1], "show-legends")) {
3452 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3453 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3454 err_code |= ERR_ALERT | ERR_ABORT;
3455 goto out;
3456 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003457 } else if (!strcmp(args[1], "show-node")) {
3458
3459 if (*args[2]) {
3460 int i;
3461 char c;
3462
3463 for (i=0; args[2][i]; i++) {
3464 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003465 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3466 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003467 break;
3468 }
3469
3470 if (!i || args[2][i]) {
3471 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3472 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3473 file, linenum, args[0], args[1]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477 }
3478
3479 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3480 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3481 err_code |= ERR_ALERT | ERR_ABORT;
3482 goto out;
3483 }
3484 } else if (!strcmp(args[1], "show-desc")) {
3485 char *desc = NULL;
3486
3487 if (*args[2]) {
3488 int i, len=0;
3489 char *d;
3490
Willy Tarreau348acfe2014-04-14 15:00:39 +02003491 for (i = 2; *args[i]; i++)
3492 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003493
3494 desc = d = (char *)calloc(1, len);
3495
Willy Tarreau348acfe2014-04-14 15:00:39 +02003496 d += snprintf(d, desc + len - d, "%s", args[2]);
3497 for (i = 3; *args[i]; i++)
3498 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003499 }
3500
3501 if (!*args[2] && !global.desc)
3502 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3503 file, linenum, args[1]);
3504 else {
3505 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3506 free(desc);
3507 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3508 err_code |= ERR_ALERT | ERR_ABORT;
3509 goto out;
3510 }
3511 free(desc);
3512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003514stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003515 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 +01003516 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
3520 }
3521 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003522 int optnum;
3523
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003524 if (*(args[1]) == '\0') {
3525 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3526 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003530
3531 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3532 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003533 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3534 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3535 file, linenum, cfg_opts[optnum].name);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
Willy Tarreau93893792009-07-23 13:19:11 +02003539 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3540 err_code |= ERR_WARN;
3541 goto out;
3542 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003543
Willy Tarreau3842f002009-06-14 11:39:52 +02003544 curproxy->no_options &= ~cfg_opts[optnum].val;
3545 curproxy->options &= ~cfg_opts[optnum].val;
3546
3547 switch (kwm) {
3548 case KWM_STD:
3549 curproxy->options |= cfg_opts[optnum].val;
3550 break;
3551 case KWM_NO:
3552 curproxy->no_options |= cfg_opts[optnum].val;
3553 break;
3554 case KWM_DEF: /* already cleared */
3555 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003556 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003557
Willy Tarreau93893792009-07-23 13:19:11 +02003558 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003559 }
3560 }
3561
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003562 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3563 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003564 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3565 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3566 file, linenum, cfg_opts2[optnum].name);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
Willy Tarreau93893792009-07-23 13:19:11 +02003570 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3571 err_code |= ERR_WARN;
3572 goto out;
3573 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003574
Willy Tarreau3842f002009-06-14 11:39:52 +02003575 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3576 curproxy->options2 &= ~cfg_opts2[optnum].val;
3577
3578 switch (kwm) {
3579 case KWM_STD:
3580 curproxy->options2 |= cfg_opts2[optnum].val;
3581 break;
3582 case KWM_NO:
3583 curproxy->no_options2 |= cfg_opts2[optnum].val;
3584 break;
3585 case KWM_DEF: /* already cleared */
3586 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003587 }
Willy Tarreau93893792009-07-23 13:19:11 +02003588 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003589 }
3590 }
3591
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003592 /* HTTP options override each other. They can be cancelled using
3593 * "no option xxx" which only switches to default mode if the mode
3594 * was this one (useful for cancelling options set in defaults
3595 * sections).
3596 */
3597 if (strcmp(args[1], "httpclose") == 0) {
3598 if (kwm == KWM_STD) {
3599 curproxy->options &= ~PR_O_HTTP_MODE;
3600 curproxy->options |= PR_O_HTTP_PCL;
3601 goto out;
3602 }
3603 else if (kwm == KWM_NO) {
3604 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3605 curproxy->options &= ~PR_O_HTTP_MODE;
3606 goto out;
3607 }
3608 }
3609 else if (strcmp(args[1], "forceclose") == 0) {
3610 if (kwm == KWM_STD) {
3611 curproxy->options &= ~PR_O_HTTP_MODE;
3612 curproxy->options |= PR_O_HTTP_FCL;
3613 goto out;
3614 }
3615 else if (kwm == KWM_NO) {
3616 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3617 curproxy->options &= ~PR_O_HTTP_MODE;
3618 goto out;
3619 }
3620 }
3621 else if (strcmp(args[1], "http-server-close") == 0) {
3622 if (kwm == KWM_STD) {
3623 curproxy->options &= ~PR_O_HTTP_MODE;
3624 curproxy->options |= PR_O_HTTP_SCL;
3625 goto out;
3626 }
3627 else if (kwm == KWM_NO) {
3628 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3629 curproxy->options &= ~PR_O_HTTP_MODE;
3630 goto out;
3631 }
3632 }
3633 else if (strcmp(args[1], "http-keep-alive") == 0) {
3634 if (kwm == KWM_STD) {
3635 curproxy->options &= ~PR_O_HTTP_MODE;
3636 curproxy->options |= PR_O_HTTP_KAL;
3637 goto out;
3638 }
3639 else if (kwm == KWM_NO) {
3640 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3641 curproxy->options &= ~PR_O_HTTP_MODE;
3642 goto out;
3643 }
3644 }
3645 else if (strcmp(args[1], "http-tunnel") == 0) {
3646 if (kwm == KWM_STD) {
3647 curproxy->options &= ~PR_O_HTTP_MODE;
3648 curproxy->options |= PR_O_HTTP_TUN;
3649 goto out;
3650 }
3651 else if (kwm == KWM_NO) {
3652 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3653 curproxy->options &= ~PR_O_HTTP_MODE;
3654 goto out;
3655 }
3656 }
3657
Willy Tarreau3842f002009-06-14 11:39:52 +02003658 if (kwm != KWM_STD) {
3659 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003660 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003663 }
3664
Emeric Brun3a058f32009-06-30 18:26:00 +02003665 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003666 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003668 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003669 if (*(args[2]) != '\0') {
3670 if (!strcmp(args[2], "clf")) {
3671 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003672 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003673 } else {
3674 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003677 }
3678 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003679 if (curproxy->conf.logformat_string != default_http_log_format &&
3680 curproxy->conf.logformat_string != default_tcp_log_format &&
3681 curproxy->conf.logformat_string != clf_http_log_format)
3682 free(curproxy->conf.logformat_string);
3683 curproxy->conf.logformat_string = logformat;
3684
3685 free(curproxy->conf.lfs_file);
3686 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3687 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003688 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003689 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003691 if (curproxy->conf.logformat_string != default_http_log_format &&
3692 curproxy->conf.logformat_string != default_tcp_log_format &&
3693 curproxy->conf.logformat_string != clf_http_log_format)
3694 free(curproxy->conf.logformat_string);
3695 curproxy->conf.logformat_string = default_tcp_log_format;
3696
3697 free(curproxy->conf.lfs_file);
3698 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3699 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 else if (!strcmp(args[1], "tcpka")) {
3702 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003703 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003705
3706 if (curproxy->cap & PR_CAP_FE)
3707 curproxy->options |= PR_O_TCP_CLI_KA;
3708 if (curproxy->cap & PR_CAP_BE)
3709 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003712 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_WARN;
3714
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003716 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003717 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003718 curproxy->options2 &= ~PR_O2_CHK_ANY;
3719 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 if (!*args[2]) { /* no argument */
3721 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3722 curproxy->check_len = strlen(DEF_CHECK_REQ);
3723 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003724 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 curproxy->check_req = (char *)malloc(reqlen);
3726 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003727 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003729 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 if (*args[4])
3731 reqlen += strlen(args[4]);
3732 else
3733 reqlen += strlen("HTTP/1.0");
3734
3735 curproxy->check_req = (char *)malloc(reqlen);
3736 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003737 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003739 }
3740 else if (!strcmp(args[1], "ssl-hello-chk")) {
3741 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003744
Willy Tarreaua534fea2008-08-03 12:19:50 +02003745 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003746 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003747 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003748 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 }
Willy Tarreau23677902007-05-08 23:50:35 +02003750 else if (!strcmp(args[1], "smtpchk")) {
3751 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003752 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003753 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003754 curproxy->options2 &= ~PR_O2_CHK_ANY;
3755 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003756
3757 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3758 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3759 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3760 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3761 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3762 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3763 curproxy->check_req = (char *)malloc(reqlen);
3764 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3765 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3766 } else {
3767 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3768 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3769 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3770 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3771 }
3772 }
3773 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003774 else if (!strcmp(args[1], "pgsql-check")) {
3775 /* use PostgreSQL request to check servers' health */
3776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3777 err_code |= ERR_WARN;
3778
3779 free(curproxy->check_req);
3780 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003781 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003782 curproxy->options2 |= PR_O2_PGSQL_CHK;
3783
3784 if (*(args[2])) {
3785 int cur_arg = 2;
3786
3787 while (*(args[cur_arg])) {
3788 if (strcmp(args[cur_arg], "user") == 0) {
3789 char * packet;
3790 uint32_t packet_len;
3791 uint32_t pv;
3792
3793 /* suboption header - needs additional argument for it */
3794 if (*(args[cur_arg+1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3796 file, linenum, args[0], args[1], args[cur_arg]);
3797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
3799 }
3800
3801 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3802 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3803 pv = htonl(0x30000); /* protocol version 3.0 */
3804
3805 packet = (char*) calloc(1, packet_len);
3806
3807 memcpy(packet + 4, &pv, 4);
3808
3809 /* copy "user" */
3810 memcpy(packet + 8, "user", 4);
3811
3812 /* copy username */
3813 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3814
3815 free(curproxy->check_req);
3816 curproxy->check_req = packet;
3817 curproxy->check_len = packet_len;
3818
3819 packet_len = htonl(packet_len);
3820 memcpy(packet, &packet_len, 4);
3821 cur_arg += 2;
3822 } else {
3823 /* unknown suboption - catchall */
3824 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3825 file, linenum, args[0], args[1]);
3826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
3828 }
3829 } /* end while loop */
3830 }
3831 }
3832
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003833 else if (!strcmp(args[1], "redis-check")) {
3834 /* use REDIS PING request to check servers' health */
3835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3836 err_code |= ERR_WARN;
3837
3838 free(curproxy->check_req);
3839 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003841 curproxy->options2 |= PR_O2_REDIS_CHK;
3842
3843 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3844 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3845 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3846 }
3847
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003848 else if (!strcmp(args[1], "mysql-check")) {
3849 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3851 err_code |= ERR_WARN;
3852
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003853 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003854 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003855 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003856 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003857
3858 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3859 * const char mysql40_client_auth_pkt[] = {
3860 * "\x0e\x00\x00" // packet length
3861 * "\x01" // packet number
3862 * "\x00\x00" // client capabilities
3863 * "\x00\x00\x01" // max packet
3864 * "haproxy\x00" // username (null terminated string)
3865 * "\x00" // filler (always 0x00)
3866 * "\x01\x00\x00" // packet length
3867 * "\x00" // packet number
3868 * "\x01" // COM_QUIT command
3869 * };
3870 */
3871
3872 if (*(args[2])) {
3873 int cur_arg = 2;
3874
3875 while (*(args[cur_arg])) {
3876 if (strcmp(args[cur_arg], "user") == 0) {
3877 char *mysqluser;
3878 int packetlen, reqlen, userlen;
3879
3880 /* suboption header - needs additional argument for it */
3881 if (*(args[cur_arg+1]) == 0) {
3882 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3883 file, linenum, args[0], args[1], args[cur_arg]);
3884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
3886 }
3887 mysqluser = args[cur_arg + 1];
3888 userlen = strlen(mysqluser);
3889 packetlen = userlen + 7;
3890 reqlen = packetlen + 9;
3891
3892 free(curproxy->check_req);
3893 curproxy->check_req = (char *)calloc(1, reqlen);
3894 curproxy->check_len = reqlen;
3895
3896 snprintf(curproxy->check_req, 4, "%c%c%c",
3897 ((unsigned char) packetlen & 0xff),
3898 ((unsigned char) (packetlen >> 8) & 0xff),
3899 ((unsigned char) (packetlen >> 16) & 0xff));
3900
3901 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003902 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003903 curproxy->check_req[8] = 1;
3904 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3905 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3906 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3907 cur_arg += 2;
3908 } else {
3909 /* unknown suboption - catchall */
3910 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3911 file, linenum, args[0], args[1]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915 } /* end while loop */
3916 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003917 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003918 else if (!strcmp(args[1], "ldap-check")) {
3919 /* use LDAP request to check servers' health */
3920 free(curproxy->check_req);
3921 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003922 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003923 curproxy->options2 |= PR_O2_LDAP_CHK;
3924
3925 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3926 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3927 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3928 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003929 else if (!strcmp(args[1], "tcp-check")) {
3930 /* use raw TCPCHK send/expect to check servers' health */
3931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3932 err_code |= ERR_WARN;
3933
3934 free(curproxy->check_req);
3935 curproxy->check_req = NULL;
3936 curproxy->options2 &= ~PR_O2_CHK_ANY;
3937 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3938 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003939 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003940 int cur_arg;
3941
3942 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3943 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003944 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003945
Willy Tarreau87cf5142011-08-19 22:57:24 +02003946 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003947
3948 free(curproxy->fwdfor_hdr_name);
3949 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3950 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3951
3952 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3953 cur_arg = 2;
3954 while (*(args[cur_arg])) {
3955 if (!strcmp(args[cur_arg], "except")) {
3956 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003957 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003958 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3959 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003962 }
3963 /* flush useless bits */
3964 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003965 cur_arg += 2;
3966 } else if (!strcmp(args[cur_arg], "header")) {
3967 /* suboption header - needs additional argument for it */
3968 if (*(args[cur_arg+1]) == 0) {
3969 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3970 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003973 }
3974 free(curproxy->fwdfor_hdr_name);
3975 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3976 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3977 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003978 } else if (!strcmp(args[cur_arg], "if-none")) {
3979 curproxy->options &= ~PR_O_FF_ALWAYS;
3980 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003981 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003982 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003983 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003984 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003987 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003988 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003989 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003990 else if (!strcmp(args[1], "originalto")) {
3991 int cur_arg;
3992
3993 /* insert x-original-to field, but not for the IP address listed as an except.
3994 * set default options (ie: bitfield, header name, etc)
3995 */
3996
3997 curproxy->options |= PR_O_ORGTO;
3998
3999 free(curproxy->orgto_hdr_name);
4000 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4001 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4002
Willy Tarreau87cf5142011-08-19 22:57:24 +02004003 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004004 cur_arg = 2;
4005 while (*(args[cur_arg])) {
4006 if (!strcmp(args[cur_arg], "except")) {
4007 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004008 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 +02004009 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4010 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004013 }
4014 /* flush useless bits */
4015 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4016 cur_arg += 2;
4017 } else if (!strcmp(args[cur_arg], "header")) {
4018 /* suboption header - needs additional argument for it */
4019 if (*(args[cur_arg+1]) == 0) {
4020 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4021 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004024 }
4025 free(curproxy->orgto_hdr_name);
4026 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4027 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4028 cur_arg += 2;
4029 } else {
4030 /* unknown suboption - catchall */
4031 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4032 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004035 }
4036 } /* end while loop */
4037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 else {
4039 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 }
Willy Tarreau93893792009-07-23 13:19:11 +02004043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004045 else if (!strcmp(args[0], "default_backend")) {
4046 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004048
4049 if (*(args[1]) == 0) {
4050 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004053 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004054 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004055 curproxy->defbe.name = strdup(args[1]);
4056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004058 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004060
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004061 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 /* enable reconnections to dispatch */
4065 curproxy->options |= PR_O_REDISP;
4066 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004067 else if (!strcmp(args[0], "http-check")) {
4068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004069 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004070
4071 if (strcmp(args[1], "disable-on-404") == 0) {
4072 /* enable a graceful server shutdown on an HTTP 404 response */
4073 curproxy->options |= PR_O_DISABLE404;
4074 }
Willy Tarreauef781042010-01-27 11:53:01 +01004075 else if (strcmp(args[1], "send-state") == 0) {
4076 /* enable emission of the apparent state of a server in HTTP checks */
4077 curproxy->options2 |= PR_O2_CHK_SNDST;
4078 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004079 else if (strcmp(args[1], "expect") == 0) {
4080 const char *ptr_arg;
4081 int cur_arg;
4082
4083 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4084 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088
4089 cur_arg = 2;
4090 /* consider exclamation marks, sole or at the beginning of a word */
4091 while (*(ptr_arg = args[cur_arg])) {
4092 while (*ptr_arg == '!') {
4093 curproxy->options2 ^= PR_O2_EXP_INV;
4094 ptr_arg++;
4095 }
4096 if (*ptr_arg)
4097 break;
4098 cur_arg++;
4099 }
4100 /* now ptr_arg points to the beginning of a word past any possible
4101 * exclamation mark, and cur_arg is the argument which holds this word.
4102 */
4103 if (strcmp(ptr_arg, "status") == 0) {
4104 if (!*(args[cur_arg + 1])) {
4105 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4106 file, linenum, args[0], args[1], ptr_arg);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004111 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004112 curproxy->expect_str = strdup(args[cur_arg + 1]);
4113 }
4114 else if (strcmp(ptr_arg, "string") == 0) {
4115 if (!*(args[cur_arg + 1])) {
4116 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4117 file, linenum, args[0], args[1], ptr_arg);
4118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
4120 }
4121 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004122 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004123 curproxy->expect_str = strdup(args[cur_arg + 1]);
4124 }
4125 else if (strcmp(ptr_arg, "rstatus") == 0) {
4126 if (!*(args[cur_arg + 1])) {
4127 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4128 file, linenum, args[0], args[1], ptr_arg);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
4132 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004133 free(curproxy->expect_str);
4134 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4135 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004136 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4137 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4138 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4139 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 }
4144 else if (strcmp(ptr_arg, "rstring") == 0) {
4145 if (!*(args[cur_arg + 1])) {
4146 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4147 file, linenum, args[0], args[1], ptr_arg);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004152 free(curproxy->expect_str);
4153 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4154 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004155 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4156 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4157 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4158 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162 }
4163 else {
4164 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4165 file, linenum, args[0], args[1], ptr_arg);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004170 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004171 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 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004174 }
4175 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004176 else if (!strcmp(args[0], "tcp-check")) {
4177 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4178 err_code |= ERR_WARN;
4179
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004180 if (strcmp(args[1], "connect") == 0) {
4181 const char *ptr_arg;
4182 int cur_arg;
4183 struct tcpcheck_rule *tcpcheck;
4184 struct list *l;
4185
4186 /* check if first rule is also a 'connect' action */
4187 l = (struct list *)&curproxy->tcpcheck_rules;
4188 if (l->p != l->n) {
4189 tcpcheck = (struct tcpcheck_rule *)l->n;
4190 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4191 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4192 file, linenum);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196 }
4197
4198 cur_arg = 2;
4199 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4200 tcpcheck->action = TCPCHK_ACT_CONNECT;
4201
4202 /* parsing each parameters to fill up the rule */
4203 while (*(ptr_arg = args[cur_arg])) {
4204 /* tcp port */
4205 if (strcmp(args[cur_arg], "port") == 0) {
4206 if ( (atol(args[cur_arg + 1]) > 65535) ||
4207 (atol(args[cur_arg + 1]) < 1) ){
4208 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4209 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
4212 }
4213 tcpcheck->port = atol(args[cur_arg + 1]);
4214 cur_arg += 2;
4215 }
4216 /* send proxy protocol */
4217 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4218 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4219 cur_arg++;
4220 }
4221#ifdef USE_OPENSSL
4222 else if (strcmp(args[cur_arg], "ssl") == 0) {
4223 curproxy->options |= PR_O_TCPCHK_SSL;
4224 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4225 cur_arg++;
4226 }
4227#endif /* USE_OPENSSL */
4228 else {
4229#ifdef USE_OPENSSL
4230 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4231#else /* USE_OPENSSL */
4232 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4233#endif /* USE_OPENSSL */
4234 file, linenum, args[0], args[1], args[cur_arg]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238
4239 }
4240
4241 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4242 }
4243 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004244 if (! *(args[2]) ) {
4245 /* SEND string expected */
4246 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4247 file, linenum, args[0], args[1], args[2]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 } else {
4251 struct tcpcheck_rule *tcpcheck;
4252
4253 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4254
4255 tcpcheck->action = TCPCHK_ACT_SEND;
4256 tcpcheck->string_len = strlen(args[2]);
4257 tcpcheck->string = strdup(args[2]);
4258 tcpcheck->expect_regex = NULL;
4259
4260 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4261 }
4262 }
4263 else if (strcmp(args[1], "send-binary") == 0) {
4264 if (! *(args[2]) ) {
4265 /* SEND binary string expected */
4266 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4267 file, linenum, args[0], args[1], args[2]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 } else {
4271 struct tcpcheck_rule *tcpcheck;
4272 char *err = NULL;
4273
4274 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4275
4276 tcpcheck->action = TCPCHK_ACT_SEND;
4277 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4278 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4279 file, linenum, args[0], args[1], args[2], err);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283 tcpcheck->expect_regex = NULL;
4284
4285 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4286 }
4287 }
4288 else if (strcmp(args[1], "expect") == 0) {
4289 const char *ptr_arg;
4290 int cur_arg;
4291 int inverse = 0;
4292
4293 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4294 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298
4299 cur_arg = 2;
4300 /* consider exclamation marks, sole or at the beginning of a word */
4301 while (*(ptr_arg = args[cur_arg])) {
4302 while (*ptr_arg == '!') {
4303 inverse = !inverse;
4304 ptr_arg++;
4305 }
4306 if (*ptr_arg)
4307 break;
4308 cur_arg++;
4309 }
4310 /* now ptr_arg points to the beginning of a word past any possible
4311 * exclamation mark, and cur_arg is the argument which holds this word.
4312 */
4313 if (strcmp(ptr_arg, "binary") == 0) {
4314 if (!*(args[cur_arg + 1])) {
4315 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4316 file, linenum, args[0], args[1], ptr_arg);
4317 err_code |= ERR_ALERT | ERR_FATAL;
4318 goto out;
4319 }
4320 struct tcpcheck_rule *tcpcheck;
4321 char *err = NULL;
4322
4323 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4324
4325 tcpcheck->action = TCPCHK_ACT_EXPECT;
4326 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4327 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4328 file, linenum, args[0], args[1], args[2], err);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332 tcpcheck->expect_regex = NULL;
4333 tcpcheck->inverse = inverse;
4334
4335 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4336 }
4337 else if (strcmp(ptr_arg, "string") == 0) {
4338 if (!*(args[cur_arg + 1])) {
4339 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4340 file, linenum, args[0], args[1], ptr_arg);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344 struct tcpcheck_rule *tcpcheck;
4345
4346 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4347
4348 tcpcheck->action = TCPCHK_ACT_EXPECT;
4349 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4350 tcpcheck->string = strdup(args[cur_arg + 1]);
4351 tcpcheck->expect_regex = NULL;
4352 tcpcheck->inverse = inverse;
4353
4354 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4355 }
4356 else if (strcmp(ptr_arg, "rstring") == 0) {
4357 if (!*(args[cur_arg + 1])) {
4358 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4359 file, linenum, args[0], args[1], ptr_arg);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 struct tcpcheck_rule *tcpcheck;
4364
4365 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4366
4367 tcpcheck->action = TCPCHK_ACT_EXPECT;
4368 tcpcheck->string_len = 0;
4369 tcpcheck->string = NULL;
4370 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4371 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4372 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4373 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
4376 }
4377 tcpcheck->inverse = inverse;
4378
4379 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4380 }
4381 else {
4382 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4383 file, linenum, args[0], args[1], ptr_arg);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387 }
4388 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004389 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004394 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004395 if (curproxy == &defproxy) {
4396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004399 }
4400
Willy Tarreaub80c2302007-11-30 20:51:32 +01004401 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004403
4404 if (strcmp(args[1], "fail") == 0) {
4405 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004406 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004407 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4408 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004411 }
4412
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004413 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4414 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4415 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004418 }
4419 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4420 }
4421 else {
4422 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004425 }
4426 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427#ifdef TPROXY
4428 else if (!strcmp(args[0], "transparent")) {
4429 /* enable transparent proxy connections */
4430 curproxy->options |= PR_O_TRANSP;
4431 }
4432#endif
4433 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004434 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004436
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 if (*(args[1]) == 0) {
4438 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
4442 curproxy->maxconn = atol(args[1]);
4443 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004444 else if (!strcmp(args[0], "backlog")) { /* backlog */
4445 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004447
4448 if (*(args[1]) == 0) {
4449 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004452 }
4453 curproxy->backlog = atol(args[1]);
4454 }
Willy Tarreau86034312006-12-29 00:10:33 +01004455 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004456 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004458
Willy Tarreau86034312006-12-29 00:10:33 +01004459 if (*(args[1]) == 0) {
4460 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004463 }
4464 curproxy->fullconn = atol(args[1]);
4465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4467 if (*(args[1]) == 0) {
4468 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004472 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4473 if (err) {
4474 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4475 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004478 }
4479 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 }
4481 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004482 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004483 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004484 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004485
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 if (curproxy == &defproxy) {
4487 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004491 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004492 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004493
Willy Tarreau902636f2013-03-10 19:44:48 +01004494 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004495 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004496 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004497 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004498 goto out;
4499 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004500
4501 proto = protocol_by_family(sk->ss_family);
4502 if (!proto || !proto->connect) {
4503 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4504 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
4508
4509 if (port1 != port2) {
4510 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4511 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004515
4516 if (!port1) {
4517 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4518 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
4521 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004522
Willy Tarreaud5191e72010-02-09 20:50:45 +01004523 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004524 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 }
4526 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004527 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004528 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004529
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004530 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4531 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004536 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004537 /**
4538 * The syntax for hash-type config element is
4539 * hash-type {map-based|consistent} [[<algo>] avalanche]
4540 *
4541 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4542 */
4543 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004544
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4546 err_code |= ERR_WARN;
4547
4548 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004549 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4550 }
4551 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004552 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4553 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004554 else if (strcmp(args[1], "avalanche") == 0) {
4555 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]);
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004558 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004559 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004560 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
Bhaskar98634f02013-10-29 23:30:51 -04004564
4565 /* set the hash function to use */
4566 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004567 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004568 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004569
4570 /* if consistent with no argument, then avalanche modifier is also applied */
4571 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4572 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004573 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004574 /* set the hash function */
4575 if (!strcmp(args[2], "sdbm")) {
4576 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4577 }
4578 else if (!strcmp(args[2], "djb2")) {
4579 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004580 } else if (!strcmp(args[2], "wt6")) {
4581 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004582 }
4583 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004584 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 -05004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588
4589 /* set the hash modifier */
4590 if (!strcmp(args[3], "avalanche")) {
4591 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4592 }
4593 else if (*args[3]) {
4594 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004598 }
William Lallemanda73203e2012-03-12 12:48:57 +01004599 }
William Lallemanda73203e2012-03-12 12:48:57 +01004600 else if (strcmp(args[0], "unique-id-format") == 0) {
4601 if (!*(args[1])) {
4602 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
William Lallemand3203ff42012-11-11 17:30:56 +01004606 if (*(args[2])) {
4607 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004611 free(curproxy->conf.uniqueid_format_string);
4612 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004613
Willy Tarreau62a61232013-04-12 18:13:46 +02004614 free(curproxy->conf.uif_file);
4615 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4616 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004617 }
William Lallemanda73203e2012-03-12 12:48:57 +01004618
4619 else if (strcmp(args[0], "unique-id-header") == 0) {
4620 if (!*(args[1])) {
4621 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 free(curproxy->header_unique_id);
4626 curproxy->header_unique_id = strdup(args[1]);
4627 }
4628
William Lallemand723b73a2012-02-08 16:37:49 +01004629 else if (strcmp(args[0], "log-format") == 0) {
4630 if (!*(args[1])) {
4631 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
William Lallemand3203ff42012-11-11 17:30:56 +01004635 if (*(args[2])) {
4636 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004640
Willy Tarreau62a61232013-04-12 18:13:46 +02004641 if (curproxy->conf.logformat_string != default_http_log_format &&
4642 curproxy->conf.logformat_string != default_tcp_log_format &&
4643 curproxy->conf.logformat_string != clf_http_log_format)
4644 free(curproxy->conf.logformat_string);
4645 curproxy->conf.logformat_string = strdup(args[1]);
4646
4647 free(curproxy->conf.lfs_file);
4648 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4649 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004650
4651 /* get a chance to improve log-format error reporting by
4652 * reporting the correct line-number when possible.
4653 */
4654 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4655 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4656 file, linenum, curproxy->id);
4657 err_code |= ERR_WARN;
4658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
William Lallemand723b73a2012-02-08 16:37:49 +01004660
William Lallemand0f99e342011-10-12 17:50:54 +02004661 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4662 /* delete previous herited or defined syslog servers */
4663 struct logsrv *back;
4664
4665 if (*(args[1]) != 0) {
4666 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670
William Lallemand723b73a2012-02-08 16:37:49 +01004671 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4672 LIST_DEL(&tmplogsrv->list);
4673 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004674 }
4675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004677 struct logsrv *logsrv;
4678
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004680 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004681 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004682 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004683 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004684 LIST_INIT(&node->list);
4685 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004689 struct sockaddr_storage *sk;
4690 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004691
4692 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693
William Lallemand0f99e342011-10-12 17:50:54 +02004694 logsrv->facility = get_log_facility(args[2]);
4695 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
4701
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004704 logsrv->level = get_log_level(args[3]);
4705 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 }
4711 }
4712
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004714 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004715 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004716 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004717 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004721 }
4722 }
4723
Willy Tarreau902636f2013-03-10 19:44:48 +01004724 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004725 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004726 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004727 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004728 goto out;
4729 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004730
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004731 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004732
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004733 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004734 if (port1 != port2) {
4735 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4736 file, linenum, args[0], args[1]);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
4740
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004741 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004742 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
William Lallemand0f99e342011-10-12 17:50:54 +02004744
4745 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
4747 else {
4748 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4749 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
4753 }
4754 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004755 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004756 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004757 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004758 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004759
Willy Tarreau977b8e42006-12-29 14:19:17 +01004760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004762
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004764 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4765 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004769
4770 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004771 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4772 free(curproxy->conn_src.iface_name);
4773 curproxy->conn_src.iface_name = NULL;
4774 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004775
Willy Tarreau902636f2013-03-10 19:44:48 +01004776 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004777 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004778 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004779 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004780 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004781 goto out;
4782 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004783
4784 proto = protocol_by_family(sk->ss_family);
4785 if (!proto || !proto->connect) {
4786 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004787 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
4790 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004791
4792 if (port1 != port2) {
4793 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4794 file, linenum, args[0], args[1]);
4795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797 }
4798
Willy Tarreauef9a3602012-12-08 22:29:20 +01004799 curproxy->conn_src.source_addr = *sk;
4800 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801
4802 cur_arg = 2;
4803 while (*(args[cur_arg])) {
4804 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004805#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4806#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004807 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004808 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4809 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004812 }
4813#endif
4814 if (!*args[cur_arg + 1]) {
4815 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4816 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004819 }
4820
4821 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004822 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4823 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004824 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004825 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4826 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004827 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4828 char *name, *end;
4829
4830 name = args[cur_arg+1] + 7;
4831 while (isspace(*name))
4832 name++;
4833
4834 end = name;
4835 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4836 end++;
4837
Willy Tarreauef9a3602012-12-08 22:29:20 +01004838 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4839 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4840 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4841 curproxy->conn_src.bind_hdr_len = end - name;
4842 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4843 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4844 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004845
4846 /* now look for an occurrence number */
4847 while (isspace(*end))
4848 end++;
4849 if (*end == ',') {
4850 end++;
4851 name = end;
4852 if (*end == '-')
4853 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004854 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004855 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004856 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004857 }
4858
Willy Tarreauef9a3602012-12-08 22:29:20 +01004859 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004860 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4861 " occurrences values smaller than %d.\n",
4862 file, linenum, MAX_HDR_HISTORY);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004866 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004867 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004868
Willy Tarreau902636f2013-03-10 19:44:48 +01004869 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004870 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004871 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004872 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004874 goto out;
4875 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004876
4877 proto = protocol_by_family(sk->ss_family);
4878 if (!proto || !proto->connect) {
4879 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4880 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004884
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004885 if (port1 != port2) {
4886 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4887 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004891 curproxy->conn_src.tproxy_addr = *sk;
4892 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 }
4894 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004895#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004896 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004897#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004898#else /* no TPROXY support */
4899 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004900 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004903#endif
4904 cur_arg += 2;
4905 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004906 }
4907
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004908 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4909#ifdef SO_BINDTODEVICE
4910 if (!*args[cur_arg + 1]) {
4911 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004915 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004916 free(curproxy->conn_src.iface_name);
4917 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4918 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004919 global.last_checks |= LSTCHK_NETADM;
4920#else
4921 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4922 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004925#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004926 cur_arg += 2;
4927 continue;
4928 }
4929 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004930 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004935 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4936 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4937 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948
4949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004950 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004951 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
4955 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004957 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
4962 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004964 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004965 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
4969 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004971 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004972 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 }
4976 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004978 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004979 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004980 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004983 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004985 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004986 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004988 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004989 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004990 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004992 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004993 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004995 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004996 }
4997 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004999 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005000 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005002 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005011
5012 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005013 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005014 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
5018 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005020 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005021 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
5025 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
5032 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
5039 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005041 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005042 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005046 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005048 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005049 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005051 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005054 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005055
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 if (curproxy == &defproxy) {
5057 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005061 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 if (*(args[1]) == 0) {
5065 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005069
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005070 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005071 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5072 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5073 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005077 err_code |= warnif_cond_conflicts(cond,
5078 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5079 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005080 }
5081 else if (*args[2]) {
5082 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5083 file, linenum, args[0], args[2]);
5084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
5086 }
5087
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005088 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005089 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005090 wl->s = strdup(args[1]);
5091 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005092 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
5094 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5097 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005101
Willy Tarreauade5ec42010-01-28 19:33:49 +01005102 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005103 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005104 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
5108 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005110 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005111 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
5115 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005117 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005118 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5125 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005131 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005132 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
5136 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005138 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005139 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005145 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005146 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005151 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005152
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 if (curproxy == &defproxy) {
5154 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005158 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 if (*(args[1]) == 0) {
5162 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005167 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005168 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5169 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5170 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005174 err_code |= warnif_cond_conflicts(cond,
5175 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5176 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005177 }
5178 else if (*args[2]) {
5179 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5180 file, linenum, args[0], args[2]);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005185 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005186 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005187 wl->s = strdup(args[1]);
5188 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 }
5190 else if (!strcmp(args[0], "errorloc") ||
5191 !strcmp(args[0], "errorloc302") ||
5192 !strcmp(args[0], "errorloc303")) { /* error location */
5193 int errnum, errlen;
5194 char *err;
5195
Willy Tarreau977b8e42006-12-29 14:19:17 +01005196 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005198
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005200 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
5204
5205 errnum = atol(args[1]);
5206 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005207 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5208 err = malloc(errlen);
5209 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005211 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5212 err = malloc(errlen);
5213 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
5215
Willy Tarreau0f772532006-12-23 20:51:41 +01005216 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5217 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005218 chunk_destroy(&curproxy->errmsg[rc]);
5219 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005220 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005223
5224 if (rc >= HTTP_ERR_SIZE) {
5225 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5226 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 free(err);
5228 }
5229 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005230 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5231 int errnum, errlen, fd;
5232 char *err;
5233 struct stat stat;
5234
5235 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005237
5238 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005239 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005242 }
5243
5244 fd = open(args[2], O_RDONLY);
5245 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5246 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5247 file, linenum, args[2], args[1]);
5248 if (fd >= 0)
5249 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252 }
5253
Willy Tarreau27a674e2009-08-17 07:23:33 +02005254 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005255 errlen = stat.st_size;
5256 } else {
5257 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005258 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005260 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005261 }
5262
5263 err = malloc(errlen); /* malloc() must succeed during parsing */
5264 errnum = read(fd, err, errlen);
5265 if (errnum != errlen) {
5266 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5267 file, linenum, args[2], args[1]);
5268 close(fd);
5269 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005272 }
5273 close(fd);
5274
5275 errnum = atol(args[1]);
5276 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5277 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005278 chunk_destroy(&curproxy->errmsg[rc]);
5279 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005280 break;
5281 }
5282 }
5283
5284 if (rc >= HTTP_ERR_SIZE) {
5285 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5286 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005288 free(err);
5289 }
5290 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005291 else if (!strcmp(args[0], "compression")) {
5292 struct comp *comp;
5293 if (curproxy->comp == NULL) {
5294 comp = calloc(1, sizeof(struct comp));
5295 curproxy->comp = comp;
5296 } else {
5297 comp = curproxy->comp;
5298 }
5299
5300 if (!strcmp(args[1], "algo")) {
5301 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005302 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005303
William Lallemand82fe75c2012-10-23 10:25:10 +02005304 cur_arg = 2;
5305 if (!*args[cur_arg]) {
5306 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5307 file, linenum, args[0]);
5308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
5311 while (*(args[cur_arg])) {
5312 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5313 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5314 file, linenum, args[0], args[cur_arg]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
William Lallemand552df672012-11-07 13:21:47 +01005318 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5319 curproxy->comp->algos->end(&ctx);
5320 } else {
5321 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5322 file, linenum, args[0], args[cur_arg]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005326 cur_arg ++;
5327 continue;
5328 }
5329 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005330 else if (!strcmp(args[1], "offload")) {
5331 comp->offload = 1;
5332 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005333 else if (!strcmp(args[1], "type")) {
5334 int cur_arg;
5335 cur_arg = 2;
5336 if (!*args[cur_arg]) {
5337 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5338 file, linenum, args[0]);
5339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
5341 }
5342 while (*(args[cur_arg])) {
5343 comp_append_type(comp, args[cur_arg]);
5344 cur_arg ++;
5345 continue;
5346 }
5347 }
5348 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005349 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005350 file, linenum, args[0]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005356 struct cfg_kw_list *kwl;
5357 int index;
5358
5359 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5360 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5361 if (kwl->kw[index].section != CFG_LISTEN)
5362 continue;
5363 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5364 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005365 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005366 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005367 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005370 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005371 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005372 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005373 err_code |= ERR_WARN;
5374 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005375 }
Willy Tarreau93893792009-07-23 13:19:11 +02005376 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005377 }
5378 }
5379 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005380
Willy Tarreau6daf3432008-01-22 16:44:08 +01005381 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 }
Willy Tarreau93893792009-07-23 13:19:11 +02005385 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005386 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388}
5389
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005390int
5391cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5392{
5393
5394 int err_code = 0;
5395 const char *err;
5396
5397 if (!strcmp(args[0], "userlist")) { /* new userlist */
5398 struct userlist *newul;
5399
5400 if (!*args[1]) {
5401 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5402 file, linenum, args[0]);
5403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
5406
5407 err = invalid_char(args[1]);
5408 if (err) {
5409 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5410 file, linenum, *err, args[0], args[1]);
5411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
5413 }
5414
5415 for (newul = userlist; newul; newul = newul->next)
5416 if (!strcmp(newul->name, args[1])) {
5417 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5418 file, linenum, args[1]);
5419 err_code |= ERR_WARN;
5420 goto out;
5421 }
5422
5423 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5424 if (!newul) {
5425 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5426 err_code |= ERR_ALERT | ERR_ABORT;
5427 goto out;
5428 }
5429
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005430 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005431 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005432 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5433 err_code |= ERR_ALERT | ERR_ABORT;
5434 goto out;
5435 }
5436
5437 newul->next = userlist;
5438 userlist = newul;
5439
5440 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005441 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005442 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005443 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005444
5445 if (!*args[1]) {
5446 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5447 file, linenum, args[0]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451
5452 err = invalid_char(args[1]);
5453 if (err) {
5454 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5455 file, linenum, *err, args[0], args[1]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
5459
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005460 for (ag = userlist->groups; ag; ag = ag->next)
5461 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005462 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5463 file, linenum, args[1], userlist->name);
5464 err_code |= ERR_ALERT;
5465 goto out;
5466 }
5467
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005468 ag = calloc(1, sizeof(*ag));
5469 if (!ag) {
5470 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5471 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005472 goto out;
5473 }
5474
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005475 ag->name = strdup(args[1]);
5476 if (!ag) {
5477 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5478 err_code |= ERR_ALERT | ERR_ABORT;
5479 goto out;
5480 }
5481
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 cur_arg = 2;
5483
5484 while (*args[cur_arg]) {
5485 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005486 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005487 cur_arg += 2;
5488 continue;
5489 } else {
5490 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5491 file, linenum, args[0]);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495 }
5496
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005497 ag->next = userlist->groups;
5498 userlist->groups = ag;
5499
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005500 } else if (!strcmp(args[0], "user")) { /* new user */
5501 struct auth_users *newuser;
5502 int cur_arg;
5503
5504 if (!*args[1]) {
5505 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5506 file, linenum, args[0]);
5507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
5509 }
5510
5511 for (newuser = userlist->users; newuser; newuser = newuser->next)
5512 if (!strcmp(newuser->user, args[1])) {
5513 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5514 file, linenum, args[1], userlist->name);
5515 err_code |= ERR_ALERT;
5516 goto out;
5517 }
5518
5519 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5520 if (!newuser) {
5521 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5522 err_code |= ERR_ALERT | ERR_ABORT;
5523 goto out;
5524 }
5525
5526 newuser->user = strdup(args[1]);
5527
5528 newuser->next = userlist->users;
5529 userlist->users = newuser;
5530
5531 cur_arg = 2;
5532
5533 while (*args[cur_arg]) {
5534 if (!strcmp(args[cur_arg], "password")) {
5535#ifndef CONFIG_HAP_CRYPT
5536 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5537 file, linenum);
5538 err_code |= ERR_ALERT;
5539#endif
5540 newuser->pass = strdup(args[cur_arg + 1]);
5541 cur_arg += 2;
5542 continue;
5543 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5544 newuser->pass = strdup(args[cur_arg + 1]);
5545 newuser->flags |= AU_O_INSECURE;
5546 cur_arg += 2;
5547 continue;
5548 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005549 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005550 cur_arg += 2;
5551 continue;
5552 } else {
5553 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5554 file, linenum, args[0]);
5555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
5558 }
5559 } else {
5560 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5561 err_code |= ERR_ALERT | ERR_FATAL;
5562 }
5563
5564out:
5565 return err_code;
5566}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567
5568/*
5569 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005570 * Returns the error code, 0 if OK, or any combination of :
5571 * - ERR_ABORT: must abort ASAP
5572 * - ERR_FATAL: we can continue parsing but not start the service
5573 * - ERR_WARN: a warning has been emitted
5574 * - ERR_ALERT: an alert has been emitted
5575 * Only the two first ones can stop processing, the two others are just
5576 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005578int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005580 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 FILE *f;
5582 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005583 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005584 struct cfg_section *cs = NULL;
5585 struct cfg_section *ics;
5586
5587 /* Register internal sections */
5588 if (!cfg_register_section("listen", cfg_parse_listen) ||
5589 !cfg_register_section("frontend", cfg_parse_listen) ||
5590 !cfg_register_section("backend", cfg_parse_listen) ||
5591 !cfg_register_section("ruleset", cfg_parse_listen) ||
5592 !cfg_register_section("defaults", cfg_parse_listen) ||
5593 !cfg_register_section("global", cfg_parse_global) ||
5594 !cfg_register_section("userlist", cfg_parse_users) ||
5595 !cfg_register_section("peers", cfg_parse_peers))
5596 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 if ((f=fopen(file,"r")) == NULL)
5599 return -1;
5600
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005601 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005602 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005603 char *end;
5604 char *args[MAX_LINE_ARGS + 1];
5605 char *line = thisline;
5606
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 linenum++;
5608
5609 end = line + strlen(line);
5610
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005611 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5612 /* Check if we reached the limit and the last char is not \n.
5613 * Watch out for the last line without the terminating '\n'!
5614 */
5615 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005616 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005617 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005618 }
5619
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005621 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 line++;
5623
5624 arg = 0;
5625 args[arg] = line;
5626
5627 while (*line && arg < MAX_LINE_ARGS) {
5628 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5629 * C equivalent value. Other combinations left unchanged (eg: \1).
5630 */
5631 if (*line == '\\') {
5632 int skip = 0;
5633 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5634 *line = line[1];
5635 skip = 1;
5636 }
5637 else if (line[1] == 'r') {
5638 *line = '\r';
5639 skip = 1;
5640 }
5641 else if (line[1] == 'n') {
5642 *line = '\n';
5643 skip = 1;
5644 }
5645 else if (line[1] == 't') {
5646 *line = '\t';
5647 skip = 1;
5648 }
5649 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005650 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 unsigned char hex1, hex2;
5652 hex1 = toupper(line[2]) - '0';
5653 hex2 = toupper(line[3]) - '0';
5654 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5655 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5656 *line = (hex1<<4) + hex2;
5657 skip = 3;
5658 }
5659 else {
5660 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663 }
5664 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005665 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 end -= skip;
5667 }
5668 line++;
5669 }
5670 else if (*line == '#' || *line == '\n' || *line == '\r') {
5671 /* end of string, end of loop */
5672 *line = 0;
5673 break;
5674 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005675 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005677 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005678 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 line++;
5680 args[++arg] = line;
5681 }
5682 else {
5683 line++;
5684 }
5685 }
5686
5687 /* empty line */
5688 if (!**args)
5689 continue;
5690
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005691 if (*line) {
5692 /* we had to stop due to too many args.
5693 * Let's terminate the string, print the offending part then cut the
5694 * last arg.
5695 */
5696 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5697 line++;
5698 *line = '\0';
5699
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005700 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005701 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005702 err_code |= ERR_ALERT | ERR_FATAL;
5703 args[arg] = line;
5704 }
5705
Willy Tarreau540abe42007-05-02 20:50:16 +02005706 /* zero out remaining args and ensure that at least one entry
5707 * is zeroed out.
5708 */
5709 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 args[arg] = line;
5711 }
5712
Willy Tarreau3842f002009-06-14 11:39:52 +02005713 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005714 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005715 char *tmp;
5716
Willy Tarreau3842f002009-06-14 11:39:52 +02005717 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005718 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005719 for (arg=0; *args[arg+1]; arg++)
5720 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005721 *tmp = '\0'; // fix the next arg to \0
5722 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005723 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005724 else if (!strcmp(args[0], "default")) {
5725 kwm = KWM_DEF;
5726 for (arg=0; *args[arg+1]; arg++)
5727 args[arg] = args[arg+1]; // shift args after inversion
5728 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005729
William Lallemand0f99e342011-10-12 17:50:54 +02005730 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5731 strcmp(args[0], "log") != 0) {
5732 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005734 }
5735
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005736 /* detect section start */
5737 list_for_each_entry(ics, &sections, list) {
5738 if (strcmp(args[0], ics->section_name) == 0) {
5739 cursection = ics->section_name;
5740 cs = ics;
5741 break;
5742 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005743 }
5744
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005746 if (cs)
5747 err_code |= cs->section_parser(file, linenum, args, kwm);
5748 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005749 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005752
5753 if (err_code & ERR_ABORT)
5754 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005756 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005758 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005759}
5760
Willy Tarreaubb925012009-07-23 13:36:36 +02005761/*
5762 * Returns the error code, 0 if OK, or any combination of :
5763 * - ERR_ABORT: must abort ASAP
5764 * - ERR_FATAL: we can continue parsing but not start the service
5765 * - ERR_WARN: a warning has been emitted
5766 * - ERR_ALERT: an alert has been emitted
5767 * Only the two first ones can stop processing, the two others are just
5768 * indicators.
5769 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005770int check_config_validity()
5771{
5772 int cfgerr = 0;
5773 struct proxy *curproxy = NULL;
5774 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005775 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005776 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005777 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005779 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 /*
5781 * Now, check for the integrity of all that we have collected.
5782 */
5783
5784 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005785 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786
Willy Tarreau193b8c62012-11-22 00:17:38 +01005787 if (!global.tune.max_http_hdr)
5788 global.tune.max_http_hdr = MAX_HTTP_HDR;
5789
5790 if (!global.tune.cookie_len)
5791 global.tune.cookie_len = CAPTURE_LEN;
5792
5793 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5794
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005795 /* Post initialisation of the users and groups lists. */
5796 err_code = userlist_postinit();
5797 if (err_code != ERR_NONE)
5798 goto out;
5799
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005800 /* first, we will invert the proxy list order */
5801 curproxy = NULL;
5802 while (proxy) {
5803 struct proxy *next;
5804
5805 next = proxy->next;
5806 proxy->next = curproxy;
5807 curproxy = proxy;
5808 if (!next)
5809 break;
5810 proxy = next;
5811 }
5812
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005814 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005815 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005816 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005817 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005818 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005819 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005820 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005821
Willy Tarreau050536d2012-10-04 08:47:34 +02005822 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005823 /* proxy ID not set, use automatic numbering with first
5824 * spare entry starting with next_pxid.
5825 */
5826 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5827 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5828 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005829 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005830 next_pxid++;
5831
Willy Tarreau55ea7572007-06-17 19:56:27 +02005832
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005834 /* ensure we don't keep listeners uselessly bound */
5835 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005836 curproxy = curproxy->next;
5837 continue;
5838 }
5839
Willy Tarreau16a21472012-11-19 12:39:59 +01005840 /* number of processes this proxy is bound to */
5841 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5842
Willy Tarreauff01a212009-03-15 13:46:16 +01005843 switch (curproxy->mode) {
5844 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005845 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005846 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005847 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5848 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005849 cfgerr++;
5850 }
5851
5852 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005853 Warning("config : servers will be ignored for %s '%s'.\n",
5854 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005855 break;
5856
5857 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005858 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005859 break;
5860
5861 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005862 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005863 break;
5864 }
5865
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005866 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005867 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005868 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005869 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5870 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005871 cfgerr++;
5872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005874 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005875 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5876 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005877 cfgerr++;
5878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005880 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005881 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5882 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005883 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005884 }
5885 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005886 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005887 /* If no LB algo is set in a backend, and we're not in
5888 * transparent mode, dispatch mode nor proxy mode, we
5889 * want to use balance roundrobin by default.
5890 */
5891 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5892 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005893 }
5894 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005895
Willy Tarreau1620ec32011-08-06 17:05:02 +02005896 if (curproxy->options & PR_O_DISPATCH)
5897 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5898 else if (curproxy->options & PR_O_HTTP_PROXY)
5899 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5900 else if (curproxy->options & PR_O_TRANSP)
5901 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005902
Willy Tarreau1620ec32011-08-06 17:05:02 +02005903 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5904 if (curproxy->options & PR_O_DISABLE404) {
5905 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5906 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5907 err_code |= ERR_WARN;
5908 curproxy->options &= ~PR_O_DISABLE404;
5909 }
5910 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5911 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5912 "send-state", proxy_type_str(curproxy), curproxy->id);
5913 err_code |= ERR_WARN;
5914 curproxy->options &= ~PR_O2_CHK_SNDST;
5915 }
Willy Tarreauef781042010-01-27 11:53:01 +01005916 }
5917
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005918 /* if a default backend was specified, let's find it */
5919 if (curproxy->defbe.name) {
5920 struct proxy *target;
5921
Alex Williams96532db2009-11-01 21:27:13 -05005922 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005923 if (!target) {
5924 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5925 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005926 cfgerr++;
5927 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005928 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5929 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005930 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005931 } else {
5932 free(curproxy->defbe.name);
5933 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005934 /* we force the backend to be present on at least all of
5935 * the frontend's processes.
5936 */
5937 target->bind_proc = curproxy->bind_proc ?
5938 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005939
5940 /* Emit a warning if this proxy also has some servers */
5941 if (curproxy->srv) {
5942 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5943 curproxy->id);
5944 err_code |= ERR_WARN;
5945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005946 }
5947 }
5948
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005949 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005950 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5951 /* map jump target for ACT_SETBE in req_rep chain */
5952 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005953 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005954 struct proxy *target;
5955
Willy Tarreaua496b602006-12-17 23:15:24 +01005956 if (exp->action != ACT_SETBE)
5957 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005958
Alex Williams96532db2009-11-01 21:27:13 -05005959 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005960 if (!target) {
5961 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5962 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005963 cfgerr++;
5964 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005965 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5966 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005967 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005968 } else {
5969 free((void *)exp->replace);
5970 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005971 /* we force the backend to be present on at least all of
5972 * the frontend's processes.
5973 */
5974 target->bind_proc = curproxy->bind_proc ?
5975 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005976 }
5977 }
5978 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005979
5980 /* find the target proxy for 'use_backend' rules */
5981 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005982 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005983 struct logformat_node *node;
5984 char *pxname;
5985
5986 /* Try to parse the string as a log format expression. If the result
5987 * of the parsing is only one entry containing a simple string, then
5988 * it's a standard string corresponding to a static rule, thus the
5989 * parsing is cancelled and be.name is restored to be resolved.
5990 */
5991 pxname = rule->be.name;
5992 LIST_INIT(&rule->be.expr);
5993 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
5994 curproxy->conf.args.file, curproxy->conf.args.line);
5995 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
5996
5997 if (!LIST_ISEMPTY(&rule->be.expr)) {
5998 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
5999 rule->dynamic = 1;
6000 free(pxname);
6001 continue;
6002 }
6003 /* simple string: free the expression and fall back to static rule */
6004 free(node->arg);
6005 free(node);
6006 }
6007
6008 rule->dynamic = 0;
6009 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006010
Alex Williams96532db2009-11-01 21:27:13 -05006011 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006012
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006013 if (!target) {
6014 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6015 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006016 cfgerr++;
6017 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006018 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6019 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006020 cfgerr++;
6021 } else {
6022 free((void *)rule->be.name);
6023 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006024 /* we force the backend to be present on at least all of
6025 * the frontend's processes.
6026 */
6027 target->bind_proc = curproxy->bind_proc ?
6028 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006029 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006030 }
6031
6032 /* find the target proxy for 'use_backend' rules */
6033 list_for_each_entry(srule, &curproxy->server_rules, list) {
6034 struct server *target = findserver(curproxy, srule->srv.name);
6035
6036 if (!target) {
6037 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6038 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6039 cfgerr++;
6040 continue;
6041 }
6042 free((void *)srule->srv.name);
6043 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006044 }
6045
Emeric Brunb982a3d2010-01-04 15:45:53 +01006046 /* find the target table for 'stick' rules */
6047 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6048 struct proxy *target;
6049
Emeric Brun1d33b292010-01-04 15:47:17 +01006050 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6051 if (mrule->flags & STK_IS_STORE)
6052 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6053
Emeric Brunb982a3d2010-01-04 15:45:53 +01006054 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006055 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006056 else
6057 target = curproxy;
6058
6059 if (!target) {
6060 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6061 curproxy->id, mrule->table.name);
6062 cfgerr++;
6063 }
6064 else if (target->table.size == 0) {
6065 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6066 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6067 cfgerr++;
6068 }
Willy Tarreau12785782012-04-27 21:37:17 +02006069 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6070 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006071 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6072 cfgerr++;
6073 }
6074 else {
6075 free((void *)mrule->table.name);
6076 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006077 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006078 }
6079 }
6080
6081 /* find the target table for 'store response' rules */
6082 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6083 struct proxy *target;
6084
Emeric Brun1d33b292010-01-04 15:47:17 +01006085 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6086
Emeric Brunb982a3d2010-01-04 15:45:53 +01006087 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006088 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006089 else
6090 target = curproxy;
6091
6092 if (!target) {
6093 Alert("Proxy '%s': unable to find store table '%s'.\n",
6094 curproxy->id, mrule->table.name);
6095 cfgerr++;
6096 }
6097 else if (target->table.size == 0) {
6098 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6099 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6100 cfgerr++;
6101 }
Willy Tarreau12785782012-04-27 21:37:17 +02006102 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6103 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006104 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6105 cfgerr++;
6106 }
6107 else {
6108 free((void *)mrule->table.name);
6109 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006110 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006111 }
6112 }
6113
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006114 /* find the target table for 'tcp-request' layer 4 rules */
6115 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6116 struct proxy *target;
6117
Willy Tarreaub4c84932013-07-23 19:15:30 +02006118 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006119 continue;
6120
6121 if (trule->act_prm.trk_ctr.table.n)
6122 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6123 else
6124 target = curproxy;
6125
6126 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006127 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6128 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006129 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006130 cfgerr++;
6131 }
6132 else if (target->table.size == 0) {
6133 Alert("Proxy '%s': table '%s' used but not configured.\n",
6134 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6135 cfgerr++;
6136 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006137 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6138 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6139 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 +01006140 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006141 cfgerr++;
6142 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006143 else {
6144 free(trule->act_prm.trk_ctr.table.n);
6145 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006146 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006147 * to pass a list of counters to track and allocate them right here using
6148 * stktable_alloc_data_type().
6149 */
6150 }
6151 }
6152
Willy Tarreaud1f96522010-08-03 19:34:32 +02006153 /* find the target table for 'tcp-request' layer 6 rules */
6154 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6155 struct proxy *target;
6156
Willy Tarreaub4c84932013-07-23 19:15:30 +02006157 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006158 continue;
6159
6160 if (trule->act_prm.trk_ctr.table.n)
6161 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6162 else
6163 target = curproxy;
6164
6165 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006166 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6167 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006168 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006169 cfgerr++;
6170 }
6171 else if (target->table.size == 0) {
6172 Alert("Proxy '%s': table '%s' used but not configured.\n",
6173 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6174 cfgerr++;
6175 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006176 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6177 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6178 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 +01006179 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006180 cfgerr++;
6181 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006182 else {
6183 free(trule->act_prm.trk_ctr.table.n);
6184 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006185 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006186 * to pass a list of counters to track and allocate them right here using
6187 * stktable_alloc_data_type().
6188 */
6189 }
6190 }
6191
Emeric Brun32da3c42010-09-23 18:39:19 +02006192 if (curproxy->table.peers.name) {
6193 struct peers *curpeers = peers;
6194
6195 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6196 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6197 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006198 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006199 break;
6200 }
6201 }
6202
6203 if (!curpeers) {
6204 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6205 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006206 free((void *)curproxy->table.peers.name);
6207 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006208 cfgerr++;
6209 }
6210 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006211 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6212 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006213 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006214 cfgerr++;
6215 }
6216 }
6217
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006218 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006219 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006220 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6221 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6222 "proxy", curproxy->id);
6223 cfgerr++;
6224 goto out_uri_auth_compat;
6225 }
6226
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006227 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006228 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006229 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006230 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006231
Willy Tarreau95fa4692010-02-01 13:05:50 +01006232 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6233 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006234
6235 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006236 uri_auth_compat_req[i++] = "realm";
6237 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6238 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006239
Willy Tarreau95fa4692010-02-01 13:05:50 +01006240 uri_auth_compat_req[i++] = "unless";
6241 uri_auth_compat_req[i++] = "{";
6242 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6243 uri_auth_compat_req[i++] = "}";
6244 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006245
Willy Tarreauff011f22011-01-06 17:51:27 +01006246 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6247 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006248 cfgerr++;
6249 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006250 }
6251
Willy Tarreauff011f22011-01-06 17:51:27 +01006252 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006253
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006254 if (curproxy->uri_auth->auth_realm) {
6255 free(curproxy->uri_auth->auth_realm);
6256 curproxy->uri_auth->auth_realm = NULL;
6257 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006258
6259 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006260 }
6261out_uri_auth_compat:
6262
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006263 /* compile the log format */
6264 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006265 if (curproxy->conf.logformat_string != default_http_log_format &&
6266 curproxy->conf.logformat_string != default_tcp_log_format &&
6267 curproxy->conf.logformat_string != clf_http_log_format)
6268 free(curproxy->conf.logformat_string);
6269 curproxy->conf.logformat_string = NULL;
6270 free(curproxy->conf.lfs_file);
6271 curproxy->conf.lfs_file = NULL;
6272 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006273 }
6274
Willy Tarreau62a61232013-04-12 18:13:46 +02006275 if (curproxy->conf.logformat_string) {
6276 curproxy->conf.args.ctx = ARGC_LOG;
6277 curproxy->conf.args.file = curproxy->conf.lfs_file;
6278 curproxy->conf.args.line = curproxy->conf.lfs_line;
6279 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006280 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006281 curproxy->conf.args.file = NULL;
6282 curproxy->conf.args.line = 0;
6283 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006284
Willy Tarreau62a61232013-04-12 18:13:46 +02006285 if (curproxy->conf.uniqueid_format_string) {
6286 curproxy->conf.args.ctx = ARGC_UIF;
6287 curproxy->conf.args.file = curproxy->conf.uif_file;
6288 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006289 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006290 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6291 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006292 curproxy->conf.args.file = NULL;
6293 curproxy->conf.args.line = 0;
6294 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006295
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006296 /* only now we can check if some args remain unresolved.
6297 * This must be done after the users and groups resolution.
6298 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006299 cfgerr += smp_resolve_args(curproxy);
6300 if (!cfgerr)
6301 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006302
Willy Tarreau2738a142006-07-08 17:28:09 +02006303 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006304 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006305 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006306 (!curproxy->timeout.connect ||
6307 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006308 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006309 " | While not properly invalid, you will certainly encounter various problems\n"
6310 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006311 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006312 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006313 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006314 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006315
Willy Tarreau1fa31262007-12-03 00:36:16 +01006316 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6317 * We must still support older configurations, so let's find out whether those
6318 * parameters have been set or must be copied from contimeouts.
6319 */
6320 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006321 if (!curproxy->timeout.tarpit ||
6322 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006323 /* tarpit timeout not set. We search in the following order:
6324 * default.tarpit, curr.connect, default.connect.
6325 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006326 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006327 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006328 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006329 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006330 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006331 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006332 }
6333 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006334 (!curproxy->timeout.queue ||
6335 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006336 /* queue timeout not set. We search in the following order:
6337 * default.queue, curr.connect, default.connect.
6338 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006339 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006340 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006341 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006342 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006343 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006344 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006345 }
6346 }
6347
Willy Tarreau1620ec32011-08-06 17:05:02 +02006348 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006349 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6350 curproxy->check_req = (char *)malloc(curproxy->check_len);
6351 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006352 }
6353
Willy Tarreau193b8c62012-11-22 00:17:38 +01006354 /* ensure that cookie capture length is not too large */
6355 if (curproxy->capture_len >= global.tune.cookie_len) {
6356 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6357 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6358 err_code |= ERR_WARN;
6359 curproxy->capture_len = global.tune.cookie_len - 1;
6360 }
6361
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006362 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006363 if (curproxy->nb_req_cap) {
6364 if (curproxy->mode == PR_MODE_HTTP) {
6365 curproxy->req_cap_pool = create_pool("ptrcap",
6366 curproxy->nb_req_cap * sizeof(char *),
6367 MEM_F_SHARED);
6368 } else {
6369 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6370 proxy_type_str(curproxy), curproxy->id);
6371 err_code |= ERR_WARN;
6372 curproxy->to_log &= ~LW_REQHDR;
6373 curproxy->nb_req_cap = 0;
6374 }
6375 }
6376
6377 if (curproxy->nb_rsp_cap) {
6378 if (curproxy->mode == PR_MODE_HTTP) {
6379 curproxy->rsp_cap_pool = create_pool("ptrcap",
6380 curproxy->nb_rsp_cap * sizeof(char *),
6381 MEM_F_SHARED);
6382 } else {
6383 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6384 proxy_type_str(curproxy), curproxy->id);
6385 err_code |= ERR_WARN;
6386 curproxy->to_log &= ~LW_REQHDR;
6387 curproxy->nb_rsp_cap = 0;
6388 }
6389 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006390
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 /* first, we will invert the servers list order */
6392 newsrv = NULL;
6393 while (curproxy->srv) {
6394 struct server *next;
6395
6396 next = curproxy->srv->next;
6397 curproxy->srv->next = newsrv;
6398 newsrv = curproxy->srv;
6399 if (!next)
6400 break;
6401 curproxy->srv = next;
6402 }
6403
Willy Tarreau17edc812014-01-03 12:14:34 +01006404 /* Check that no server name conflicts. This causes trouble in the stats.
6405 * We only emit a warning for the first conflict affecting each server,
6406 * in order to avoid combinatory explosion if all servers have the same
6407 * name. We do that only for servers which do not have an explicit ID,
6408 * because these IDs were made also for distinguishing them and we don't
6409 * want to annoy people who correctly manage them.
6410 */
6411 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6412 struct server *other_srv;
6413
6414 if (newsrv->puid)
6415 continue;
6416
6417 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6418 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6419 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6420 newsrv->conf.file, newsrv->conf.line,
6421 proxy_type_str(curproxy), curproxy->id,
6422 newsrv->id, other_srv->conf.line);
6423 break;
6424 }
6425 }
6426 }
6427
Willy Tarreaudd701652010-05-25 23:03:02 +02006428 /* assign automatic UIDs to servers which don't have one yet */
6429 next_id = 1;
6430 newsrv = curproxy->srv;
6431 while (newsrv != NULL) {
6432 if (!newsrv->puid) {
6433 /* server ID not set, use automatic numbering with first
6434 * spare entry starting with next_svid.
6435 */
6436 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6437 newsrv->conf.id.key = newsrv->puid = next_id;
6438 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6439 }
6440 next_id++;
6441 newsrv = newsrv->next;
6442 }
6443
Willy Tarreau20697042007-11-15 23:26:18 +01006444 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006445 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446
Willy Tarreau62c3be22012-01-20 13:12:32 +01006447 /*
6448 * If this server supports a maxconn parameter, it needs a dedicated
6449 * tasks to fill the emptied slots when a connection leaves.
6450 * Also, resolve deferred tracking dependency if needed.
6451 */
6452 newsrv = curproxy->srv;
6453 while (newsrv != NULL) {
6454 if (newsrv->minconn > newsrv->maxconn) {
6455 /* Only 'minconn' was specified, or it was higher than or equal
6456 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6457 * this will avoid further useless expensive computations.
6458 */
6459 newsrv->maxconn = newsrv->minconn;
6460 } else if (newsrv->maxconn && !newsrv->minconn) {
6461 /* minconn was not specified, so we set it to maxconn */
6462 newsrv->minconn = newsrv->maxconn;
6463 }
6464
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006465#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006466 if (newsrv->use_ssl || newsrv->check.use_ssl)
6467 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006468#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006469
Willy Tarreau2f075e92013-12-03 11:11:34 +01006470 /* set the check type on the server */
6471 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6472
Willy Tarreau62c3be22012-01-20 13:12:32 +01006473 if (newsrv->trackit) {
6474 struct proxy *px;
6475 struct server *srv;
6476 char *pname, *sname;
6477
6478 pname = newsrv->trackit;
6479 sname = strrchr(pname, '/');
6480
6481 if (sname)
6482 *sname++ = '\0';
6483 else {
6484 sname = pname;
6485 pname = NULL;
6486 }
6487
6488 if (pname) {
6489 px = findproxy(pname, PR_CAP_BE);
6490 if (!px) {
6491 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6492 proxy_type_str(curproxy), curproxy->id,
6493 newsrv->id, pname);
6494 cfgerr++;
6495 goto next_srv;
6496 }
6497 } else
6498 px = curproxy;
6499
6500 srv = findserver(px, sname);
6501 if (!srv) {
6502 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6503 proxy_type_str(curproxy), curproxy->id,
6504 newsrv->id, sname);
6505 cfgerr++;
6506 goto next_srv;
6507 }
6508
Willy Tarreauff5ae352013-12-11 20:36:34 +01006509 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006510 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6511 "tracking as it does not have checks enabled.\n",
6512 proxy_type_str(curproxy), curproxy->id,
6513 newsrv->id, px->id, srv->id);
6514 cfgerr++;
6515 goto next_srv;
6516 }
6517
6518 if (curproxy != px &&
6519 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6520 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6521 "tracking: disable-on-404 option inconsistency.\n",
6522 proxy_type_str(curproxy), curproxy->id,
6523 newsrv->id, px->id, srv->id);
6524 cfgerr++;
6525 goto next_srv;
6526 }
6527
6528 /* if the other server is forced disabled, we have to do the same here */
6529 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006530 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006531 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006532 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006533 }
6534
6535 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006536 newsrv->tracknext = srv->trackers;
6537 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006538
6539 free(newsrv->trackit);
6540 newsrv->trackit = NULL;
6541 }
6542 next_srv:
6543 newsrv = newsrv->next;
6544 }
6545
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006546 /* We have to initialize the server lookup mechanism depending
6547 * on what LB algorithm was choosen.
6548 */
6549
6550 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6551 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6552 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006553 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6554 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6555 init_server_map(curproxy);
6556 } else {
6557 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6558 fwrr_init_server_groups(curproxy);
6559 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006560 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006561
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006562 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006563 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6564 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6565 fwlc_init_server_tree(curproxy);
6566 } else {
6567 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6568 fas_init_server_tree(curproxy);
6569 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006570 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006571
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006572 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006573 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6574 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6575 chash_init_server_tree(curproxy);
6576 } else {
6577 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6578 init_server_map(curproxy);
6579 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006580 break;
6581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582
6583 if (curproxy->options & PR_O_LOGASAP)
6584 curproxy->to_log &= ~LW_BYTES;
6585
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006586 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006587 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006588 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6589 proxy_type_str(curproxy), curproxy->id);
6590 err_code |= ERR_WARN;
6591 }
6592
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006593 if (curproxy->mode != PR_MODE_HTTP) {
6594 int optnum;
6595
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006596 if (curproxy->uri_auth) {
6597 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6598 proxy_type_str(curproxy), curproxy->id);
6599 err_code |= ERR_WARN;
6600 curproxy->uri_auth = NULL;
6601 }
6602
Willy Tarreau87cf5142011-08-19 22:57:24 +02006603 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006604 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6605 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6606 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006607 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006608 }
6609
6610 if (curproxy->options & PR_O_ORGTO) {
6611 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6612 "originalto", proxy_type_str(curproxy), curproxy->id);
6613 err_code |= ERR_WARN;
6614 curproxy->options &= ~PR_O_ORGTO;
6615 }
6616
6617 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6618 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6619 (curproxy->cap & cfg_opts[optnum].cap) &&
6620 (curproxy->options & cfg_opts[optnum].val)) {
6621 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6622 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6623 err_code |= ERR_WARN;
6624 curproxy->options &= ~cfg_opts[optnum].val;
6625 }
6626 }
6627
6628 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6629 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6630 (curproxy->cap & cfg_opts2[optnum].cap) &&
6631 (curproxy->options2 & cfg_opts2[optnum].val)) {
6632 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6633 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6634 err_code |= ERR_WARN;
6635 curproxy->options2 &= ~cfg_opts2[optnum].val;
6636 }
6637 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006638
Pieter Baauwd551fb52013-05-08 22:49:23 +02006639#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006640 if (curproxy->conn_src.bind_hdr_occ) {
6641 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006642 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006643 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006644 err_code |= ERR_WARN;
6645 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006646#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006647 }
6648
Willy Tarreaubaaee002006-06-26 02:48:02 +02006649 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006650 * ensure that we're not cross-dressing a TCP server into HTTP.
6651 */
6652 newsrv = curproxy->srv;
6653 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006654 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006655 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6656 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006657 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006658 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006659
Willy Tarreau0cec3312011-10-31 13:49:26 +01006660 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6661 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6662 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6663 err_code |= ERR_WARN;
6664 }
6665
Willy Tarreau82ffa392013-08-13 17:19:08 +02006666 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6667 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6668 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6669 err_code |= ERR_WARN;
6670 }
6671
Pieter Baauwd551fb52013-05-08 22:49:23 +02006672#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006673 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6674 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006675 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 +01006676 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006677 err_code |= ERR_WARN;
6678 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006679#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006680 newsrv = newsrv->next;
6681 }
6682
Willy Tarreauc1a21672009-08-16 22:37:44 +02006683 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006684 if (!curproxy->accept)
6685 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006686
Willy Tarreauc1a21672009-08-16 22:37:44 +02006687 if (curproxy->tcp_req.inspect_delay ||
6688 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006689 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006690
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006691 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006692 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006693 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006694 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006695
6696 /* both TCP and HTTP must check switching rules */
6697 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6698 }
6699
6700 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006701 if (curproxy->tcp_req.inspect_delay ||
6702 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6703 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6704
Emeric Brun97679e72010-09-23 17:56:44 +02006705 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6706 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6707
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006708 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006709 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006710 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006711 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006712
6713 /* If the backend does requires RDP cookie persistence, we have to
6714 * enable the corresponding analyser.
6715 */
6716 if (curproxy->options2 & PR_O2_RDPC_PRST)
6717 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6718 }
6719
Emeric Brunc52962f2012-11-15 18:28:02 +01006720#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006721 /* Configure SSL for each bind line.
6722 * Note: if configuration fails at some point, the ->ctx member
6723 * remains NULL so that listeners can later detach.
6724 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006725 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006726 if (!bind_conf->is_ssl) {
6727 if (bind_conf->default_ctx) {
6728 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6729 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6730 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006731 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006732 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006733 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006734 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006735 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006736 cfgerr++;
6737 continue;
6738 }
6739
Emeric Brun4b3091e2012-09-24 15:48:52 +02006740 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006741 Alert("Unable to allocate SSL session cache.\n");
6742 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006743 continue;
6744 }
6745
Emeric Brunfc0421f2012-09-07 17:30:07 +02006746 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006747 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006748 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006749#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006750
Willy Tarreaue6b98942007-10-29 01:09:36 +01006751 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006752 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006753 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006754 if (!listener->luid) {
6755 /* listener ID not set, use automatic numbering with first
6756 * spare entry starting with next_luid.
6757 */
6758 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6759 listener->conf.id.key = listener->luid = next_id;
6760 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006761 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006762 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006763
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006764 /* enable separate counters */
6765 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6766 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006767 if (!listener->name)
6768 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006769 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006770
Willy Tarreaue6b98942007-10-29 01:09:36 +01006771 if (curproxy->options & PR_O_TCP_NOLING)
6772 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006773 if (!listener->maxconn)
6774 listener->maxconn = curproxy->maxconn;
6775 if (!listener->backlog)
6776 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006777 if (!listener->maxaccept)
6778 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6779
6780 /* we want to have an optimal behaviour on single process mode to
6781 * maximize the work at once, but in multi-process we want to keep
6782 * some fairness between processes, so we target half of the max
6783 * number of events to be balanced over all the processes the proxy
6784 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6785 * used to disable the limit.
6786 */
6787 if (listener->maxaccept > 0) {
6788 if (nbproc > 1)
6789 listener->maxaccept = (listener->maxaccept + 1) / 2;
6790 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6791 }
6792
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006793 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006794 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006795 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006796 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006797
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006798 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6799 listener->options |= LI_O_TCP_RULES;
6800
Willy Tarreaude3041d2010-05-31 10:56:17 +02006801 if (curproxy->mon_mask.s_addr)
6802 listener->options |= LI_O_CHK_MONNET;
6803
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006804 /* smart accept mode is automatic in HTTP mode */
6805 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006806 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006807 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6808 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006809 }
6810
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006811 /* Release unused SSL configs */
6812 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6813 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006814 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006815#ifdef USE_OPENSSL
6816 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006817 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006818 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006819 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006820 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006821#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006822 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006823
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006824 /* Check multi-process mode compatibility for the current proxy */
6825 if (global.nbproc > 1) {
6826 int nbproc = 0;
6827 if (curproxy->bind_proc) {
6828 int proc;
6829 for (proc = 0; proc < global.nbproc; proc++) {
6830 if (curproxy->bind_proc & (1 << proc)) {
6831 nbproc++;
6832 }
6833 }
6834 } else {
6835 nbproc = global.nbproc;
6836 }
6837 if (curproxy->table.peers.name) {
6838 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6839 curproxy->id);
6840 cfgerr++;
6841 }
6842 if (nbproc > 1) {
6843 if (curproxy->uri_auth) {
6844 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6845 curproxy->id);
6846 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6847 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6848 curproxy->id);
6849 }
6850 }
6851 if (curproxy->appsession_name) {
6852 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6853 curproxy->id);
6854 }
6855 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6856 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6857 curproxy->id);
6858 }
6859 }
6860 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006861
6862 /* create the task associated with the proxy */
6863 curproxy->task = task_new();
6864 if (curproxy->task) {
6865 curproxy->task->context = curproxy;
6866 curproxy->task->process = manage_proxy;
6867 /* no need to queue, it will be done automatically if some
6868 * listener gets limited.
6869 */
6870 curproxy->task->expire = TICK_ETERNITY;
6871 } else {
6872 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6873 curproxy->id);
6874 cfgerr++;
6875 }
6876
Willy Tarreaubaaee002006-06-26 02:48:02 +02006877 curproxy = curproxy->next;
6878 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006879
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006880 /* Check multi-process mode compatibility */
6881 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006882 if (global.stats_fe && !global.stats_fe->bind_proc) {
6883 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 +01006884 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006885 }
6886
6887 /* automatically compute fullconn if not set. We must not do it in the
6888 * loop above because cross-references are not yet fully resolved.
6889 */
6890 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6891 /* If <fullconn> is not set, let's set it to 10% of the sum of
6892 * the possible incoming frontend's maxconns.
6893 */
6894 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6895 struct proxy *fe;
6896 int total = 0;
6897
6898 /* sum up the number of maxconns of frontends which
6899 * reference this backend at least once or which are
6900 * the same one ('listen').
6901 */
6902 for (fe = proxy; fe; fe = fe->next) {
6903 struct switching_rule *rule;
6904 struct hdr_exp *exp;
6905 int found = 0;
6906
6907 if (!(fe->cap & PR_CAP_FE))
6908 continue;
6909
6910 if (fe == curproxy) /* we're on a "listen" instance */
6911 found = 1;
6912
6913 if (fe->defbe.be == curproxy) /* "default_backend" */
6914 found = 1;
6915
6916 /* check if a "use_backend" rule matches */
6917 if (!found) {
6918 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006919 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006920 found = 1;
6921 break;
6922 }
6923 }
6924 }
6925
6926 /* check if a "reqsetbe" rule matches */
6927 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6928 if (exp->action == ACT_SETBE &&
6929 (struct proxy *)exp->replace == curproxy) {
6930 found = 1;
6931 break;
6932 }
6933 }
6934
6935 /* now we've checked all possible ways to reference a backend
6936 * from a frontend.
6937 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006938 if (!found)
6939 continue;
6940 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006941 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006942 /* we have the sum of the maxconns in <total>. We only
6943 * keep 10% of that sum to set the default fullconn, with
6944 * a hard minimum of 1 (to avoid a divide by zero).
6945 */
6946 curproxy->fullconn = (total + 9) / 10;
6947 if (!curproxy->fullconn)
6948 curproxy->fullconn = 1;
6949 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006950 }
6951
Willy Tarreau056f5682010-06-06 15:51:11 +02006952 /* initialize stick-tables on backend capable proxies. This must not
6953 * be done earlier because the data size may be discovered while parsing
6954 * other proxies.
6955 */
Godbach9703e662013-12-11 21:11:41 +08006956 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006957 if (curproxy->state == PR_STSTOPPED)
6958 continue;
6959
Godbach9703e662013-12-11 21:11:41 +08006960 if (!stktable_init(&curproxy->table)) {
6961 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6962 cfgerr++;
6963 }
6964 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006965
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006966 /*
6967 * Recount currently required checks.
6968 */
6969
6970 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6971 int optnum;
6972
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006973 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6974 if (curproxy->options & cfg_opts[optnum].val)
6975 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006976
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006977 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6978 if (curproxy->options2 & cfg_opts2[optnum].val)
6979 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006980 }
6981
Willy Tarreau122541c2011-09-07 21:24:49 +02006982 if (peers) {
6983 struct peers *curpeers = peers, **last;
6984 struct peer *p, *pb;
6985
6986 /* Remove all peers sections which don't have a valid listener.
6987 * This can happen when a peers section is never referenced and
6988 * does not contain a local peer.
6989 */
6990 last = &peers;
6991 while (*last) {
6992 curpeers = *last;
6993 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01006994 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02006995 last = &curpeers->next;
6996 continue;
6997 }
6998
6999 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7000 curpeers->id, localpeer);
7001
7002 p = curpeers->remote;
7003 while (p) {
7004 pb = p->next;
7005 free(p->id);
7006 free(p);
7007 p = pb;
7008 }
7009
7010 /* Destroy and unlink this curpeers section.
7011 * Note: curpeers is backed up into *last.
7012 */
7013 free(curpeers->id);
7014 curpeers = curpeers->next;
7015 free(*last);
7016 *last = curpeers;
7017 }
7018 }
7019
Willy Tarreau34eb6712011-10-24 18:15:04 +02007020 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007021 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007022 MEM_F_SHARED);
7023
Willy Tarreaubb925012009-07-23 13:36:36 +02007024 if (cfgerr > 0)
7025 err_code |= ERR_ALERT | ERR_FATAL;
7026 out:
7027 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007028}
7029
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007030/*
7031 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7032 * parsing sessions.
7033 */
7034void cfg_register_keywords(struct cfg_kw_list *kwl)
7035{
7036 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7037}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007038
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007039/*
7040 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7041 */
7042void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7043{
7044 LIST_DEL(&kwl->list);
7045 LIST_INIT(&kwl->list);
7046}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007047
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007048/* this function register new section in the haproxy configuration file.
7049 * <section_name> is the name of this new section and <section_parser>
7050 * is the called parser. If two section declaration have the same name,
7051 * only the first declared is used.
7052 */
7053int cfg_register_section(char *section_name,
7054 int (*section_parser)(const char *, int, char **, int))
7055{
7056 struct cfg_section *cs;
7057
7058 cs = calloc(1, sizeof(*cs));
7059 if (!cs) {
7060 Alert("register section '%s': out of memory.\n", section_name);
7061 return 0;
7062 }
7063
7064 cs->section_name = section_name;
7065 cs->section_parser = section_parser;
7066
7067 LIST_ADDQ(&sections, &cs->list);
7068
7069 return 1;
7070}
7071
Willy Tarreaubaaee002006-06-26 02:48:02 +02007072/*
7073 * Local variables:
7074 * c-indent-level: 8
7075 * c-basic-offset: 8
7076 * End:
7077 */