blob: f7dcf061b5ac64dff38236e15c5cbf83150cb899 [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 Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int 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 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
275 l->fd = -1;
276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200594#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 else if (!strcmp(args[0], "tune.bufsize")) {
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.bufsize = atol(args[1]);
602 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
603 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100604 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200605 }
606 else if (!strcmp(args[0], "tune.maxrewrite")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.maxrewrite = atol(args[1]);
613 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
614 global.tune.maxrewrite = global.tune.bufsize / 2;
615 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100616 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
617 if (global.tune.client_rcvbuf != 0) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.client_rcvbuf = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
630 if (global.tune.server_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
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.server_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.sndbuf.client")) {
643 if (global.tune.client_sndbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.client_sndbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.server")) {
656 if (global.tune.server_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.server_sndbuf = atol(args[1]);
667 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200668 else if (!strcmp(args[0], "tune.pipesize")) {
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.pipesize = atol(args[1]);
675 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100676 else if (!strcmp(args[0], "tune.http.cookielen")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.cookie_len = atol(args[1]) + 1;
683 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200684 else if (!strcmp(args[0], "tune.http.maxhdr")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.max_http_hdr = atol(args[1]);
691 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100692 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
693#ifdef USE_ZLIB
694 if (*args[1]) {
695 global.tune.zlibmemlevel = atoi(args[1]);
696 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
697 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
698 file, linenum, args[0]);
699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
701 }
702 } else {
703 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
704 file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708#else
709 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712#endif
713 }
714 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
715#ifdef USE_ZLIB
716 if (*args[1]) {
717 global.tune.zlibwindowsize = atoi(args[1]);
718 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
719 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
720 file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 } else {
725 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
726 file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730#else
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734#endif
735 }
William Lallemandf3747832012-11-09 12:33:10 +0100736 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
737 if (*args[1]) {
738 global.tune.comp_maxlevel = atoi(args[1]);
739 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
740 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 } else {
746 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
747 file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 else if (!strcmp(args[0], "uid")) {
753 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200754 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.uid = atol(args[1]);
764 }
765 else if (!strcmp(args[0], "gid")) {
766 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200767 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 global.gid = atol(args[1]);
777 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200778 /* user/group name handling */
779 else if (!strcmp(args[0], "user")) {
780 struct passwd *ha_user;
781 if (global.uid != 0) {
782 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 }
786 errno = 0;
787 ha_user = getpwnam(args[1]);
788 if (ha_user != NULL) {
789 global.uid = (int)ha_user->pw_uid;
790 }
791 else {
792 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 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 }
796 else if (!strcmp(args[0], "group")) {
797 struct group *ha_group;
798 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200799 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 errno = 0;
804 ha_group = getgrnam(args[1]);
805 if (ha_group != NULL) {
806 global.gid = (int)ha_group->gr_gid;
807 }
808 else {
809 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 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 }
813 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 global.nbproc = atol(args[1]);
821 }
822 else if (!strcmp(args[0], "maxconn")) {
823 if (global.maxconn != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 global.maxconn = atol(args[1]);
834#ifdef SYSTEM_MAXCONN
835 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
836 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);
837 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840#endif /* SYSTEM_MAXCONN */
841 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200842 else if (!strcmp(args[0], "maxsslconn")) {
843#ifdef USE_OPENSSL
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.maxsslconn = atol(args[1]);
850#else
Emeric Brun0914df82012-10-02 18:45:42 +0200851 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200854#endif
855 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200856 else if (!strcmp(args[0], "maxconnrate")) {
857 if (global.cps_lim != 0) {
858 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT;
860 goto out;
861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.cps_lim = atol(args[1]);
868 }
William Lallemandd85f9172012-11-09 17:05:39 +0100869 else if (!strcmp(args[0], "maxcomprate")) {
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.comp_rate_lim = atoi(args[1]) * 1024;
876 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100877 else if (!strcmp(args[0], "maxpipes")) {
878 if (global.maxpipes != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT;
881 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100887 }
888 global.maxpipes = atol(args[1]);
889 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100890 else if (!strcmp(args[0], "maxzlibmem")) {
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
William Lallemande3a7d992012-11-20 11:25:20 +0100896 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100898 else if (!strcmp(args[0], "maxcompcpuusage")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 compress_min_idle = 100 - atoi(args[1]);
905 if (compress_min_idle < 0 || compress_min_idle > 100) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910}
911
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 else if (!strcmp(args[0], "ulimit-n")) {
913 if (global.rlimit_nofile != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 global.rlimit_nofile = atol(args[1]);
924 }
925 else if (!strcmp(args[0], "chroot")) {
926 if (global.chroot != NULL) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.chroot = strdup(args[1]);
937 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200938 else if (!strcmp(args[0], "description")) {
939 int i, len=0;
940 char *d;
941
942 if (!*args[1]) {
943 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
944 file, linenum, args[0]);
945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
947 }
948
949 for(i=1; *args[i]; i++)
950 len += strlen(args[i])+1;
951
952 if (global.desc)
953 free(global.desc);
954
955 global.desc = d = (char *)calloc(1, len);
956
957 d += sprintf(d, "%s", args[1]);
958 for(i=2; *args[i]; i++)
959 d += sprintf(d, " %s", args[i]);
960 }
961 else if (!strcmp(args[0], "node")) {
962 int i;
963 char c;
964
965 for (i=0; args[1][i]; i++) {
966 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100967 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
968 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200969 break;
970 }
971
972 if (!i || args[1][i]) {
973 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
974 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
975 file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
980 if (global.node)
981 free(global.node);
982
983 global.node = strdup(args[1]);
984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 else if (!strcmp(args[0], "pidfile")) {
986 if (global.pidfile != NULL) {
987 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991 if (*(args[1]) == 0) {
992 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 }
996 global.pidfile = strdup(args[1]);
997 }
Emeric Bruned760922010-10-22 17:59:25 +0200998 else if (!strcmp(args[0], "unix-bind")) {
999 int cur_arg = 1;
1000 while (*(args[cur_arg])) {
1001 if (!strcmp(args[cur_arg], "prefix")) {
1002 if (global.unix_bind.prefix != NULL) {
1003 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1004 err_code |= ERR_ALERT;
1005 cur_arg += 2;
1006 continue;
1007 }
1008
1009 if (*(args[cur_arg+1]) == 0) {
1010 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1015 cur_arg += 2;
1016 continue;
1017 }
1018
1019 if (!strcmp(args[cur_arg], "mode")) {
1020
1021 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "uid")) {
1027
1028 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "gid")) {
1034
1035 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "user")) {
1041 struct passwd *user;
1042
1043 user = getpwnam(args[cur_arg + 1]);
1044 if (!user) {
1045 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1046 file, linenum, args[0], args[cur_arg + 1 ]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 global.unix_bind.ux.uid = user->pw_uid;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (!strcmp(args[cur_arg], "group")) {
1057 struct group *group;
1058
1059 group = getgrnam(args[cur_arg + 1]);
1060 if (!group) {
1061 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1062 file, linenum, args[0], args[cur_arg + 1 ]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 global.unix_bind.ux.gid = group->gr_gid;
1068 cur_arg += 2;
1069 continue;
1070 }
1071
Willy Tarreaub48f9582011-09-05 01:17:06 +02001072 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001073 file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 }
William Lallemand0f99e342011-10-12 17:50:54 +02001078 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1079 /* delete previous herited or defined syslog servers */
1080 struct logsrv *back;
1081 struct logsrv *tmp;
1082
1083 if (*(args[1]) != 0) {
1084 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088
1089 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1090 LIST_DEL(&tmp->list);
1091 free(tmp);
1092 }
1093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001095 struct logsrv *logsrv;
1096
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 if (*(args[1]) == 0 || *(args[2]) == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
William Lallemand0f99e342011-10-12 17:50:54 +02001102
1103 logsrv = calloc(1, sizeof(struct logsrv));
1104
1105 logsrv->facility = get_log_facility(args[2]);
1106 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111
William Lallemand0f99e342011-10-12 17:50:54 +02001112 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->level = get_log_level(args[3]);
1115 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001123 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->minlvl = get_log_level(args[4]);
1125 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001126 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001129 }
1130 }
1131
Robert Tsai81ae1952007-12-05 10:47:29 +01001132 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001133 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001134 if (!sk) {
1135 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001136 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001139 goto out;
1140 }
William Lallemand0f99e342011-10-12 17:50:54 +02001141 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001142 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001143 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001144 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001145 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001147 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001148 goto out;
1149 }
William Lallemand0f99e342011-10-12 17:50:54 +02001150 logsrv->addr = *sk;
1151 if (!get_host_port(&logsrv->addr))
1152 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154
William Lallemand0f99e342011-10-12 17:50:54 +02001155 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001156 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001157 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1158 char *name;
1159 int len;
1160
1161 if (global.log_send_hostname != NULL) {
1162 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT;
1164 goto out;
1165 }
1166
1167 if (*(args[1]))
1168 name = args[1];
1169 else
1170 name = hostname;
1171
1172 len = strlen(name);
1173
1174 /* We'll add a space after the name to respect the log format */
1175 free(global.log_send_hostname);
1176 global.log_send_hostname = malloc(len + 2);
1177 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1178 }
Kevinm48936af2010-12-22 16:08:21 +00001179 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.log_tag);
1186 global.log_tag = strdup(args[1]);
1187 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001188 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1189 if (global.spread_checks != 0) {
1190 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 }
1199 global.spread_checks = atol(args[1]);
1200 if (global.spread_checks < 0 || global.spread_checks > 50) {
1201 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001205 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1206#ifdef USE_CPU_AFFINITY
1207 int cur_arg, i;
1208 unsigned int proc = 0;
1209 unsigned long cpus = 0;
1210
1211 if (strcmp(args[1], "all") == 0)
1212 proc = 0xFFFFFFFF;
1213 else if (strcmp(args[1], "odd") == 0)
1214 proc = 0x55555555;
1215 else if (strcmp(args[1], "even") == 0)
1216 proc = 0xAAAAAAAA;
1217 else {
1218 proc = atoi(args[1]);
1219 if (proc >= 1 && proc <= 32)
1220 proc = 1 << (proc - 1);
1221 }
1222
1223 if (!proc || !*args[2]) {
1224 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",
1225 file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 cur_arg = 2;
1231 while (*args[cur_arg]) {
1232 unsigned int low, high;
1233
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001234 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001235 char *dash = strchr(args[cur_arg], '-');
1236
1237 low = high = str2uic(args[cur_arg]);
1238 if (dash)
1239 high = str2uic(dash + 1);
1240
1241 if (high < low) {
1242 unsigned int swap = low;
1243 low = high;
1244 high = swap;
1245 }
1246
1247 if (low < 0 || high >= sizeof(long) * 8) {
1248 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1249 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
1254 while (low <= high)
1255 cpus |= 1UL << low++;
1256 }
1257 else {
1258 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 cur_arg++;
1264 }
1265 for (i = 0; i < 32; i++)
1266 if (proc & (1 << i))
1267 global.cpu_map[i] = cpus;
1268#else
1269 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272#endif
1273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001275 struct cfg_kw_list *kwl;
1276 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001277 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001278
1279 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1280 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1281 if (kwl->kw[index].section != CFG_GLOBAL)
1282 continue;
1283 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001284 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001285 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001286 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001289 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001290 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_WARN;
1292 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001293 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001295 }
1296 }
1297 }
1298
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001302
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001304 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306}
1307
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001308void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001310 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 defproxy.mode = PR_MODE_TCP;
1312 defproxy.state = PR_STNEW;
1313 defproxy.maxconn = cfg_maxpconn;
1314 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315
1316 defproxy.defsrv.inter = DEF_CHKINTR;
1317 defproxy.defsrv.fastinter = 0;
1318 defproxy.defsrv.downinter = 0;
1319 defproxy.defsrv.rise = DEF_RISETIME;
1320 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001321 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001322 defproxy.defsrv.maxqueue = 0;
1323 defproxy.defsrv.minconn = 0;
1324 defproxy.defsrv.maxconn = 0;
1325 defproxy.defsrv.slowstart = 0;
1326 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1327 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1328 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329}
1330
Willy Tarreauade5ec42010-01-28 19:33:49 +01001331
1332static int create_cond_regex_rule(const char *file, int line,
1333 struct proxy *px, int dir, int action, int flags,
1334 const char *cmd, const char *reg, const char *repl,
1335 const char **cond_start)
1336{
1337 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001338 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001339 const char *err;
1340 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001341 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001342
1343 if (px == &defproxy) {
1344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto err;
1347 }
1348
1349 if (*reg == 0) {
1350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto err;
1353 }
1354
1355 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1356 err_code |= ERR_WARN;
1357
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 if (cond_start &&
1359 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001360 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1361 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1362 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366 }
1367 else if (cond_start && **cond_start) {
1368 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1369 file, line, cmd, *cond_start);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto err;
1372 }
1373
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001374 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001376 else
1377 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378
Willy Tarreauade5ec42010-01-28 19:33:49 +01001379 preg = calloc(1, sizeof(regex_t));
1380 if (!preg) {
1381 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1382 err_code = ERR_ALERT | ERR_FATAL;
1383 goto err;
1384 }
1385
1386 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1387 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1388 err_code = ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001392 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001393 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 if (repl && err) {
1395 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1396 file, line, cmd, *err);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto err;
1399 }
1400
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001401 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001402 err_code |= ERR_WARN;
1403
Willy Tarreauf4068b62012-05-08 17:37:49 +02001404 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001405 return err_code;
1406 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001407 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001408 free(preg);
1409 return err_code;
1410}
1411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001414 * Returns the error code, 0 if OK, or any combination of :
1415 * - ERR_ABORT: must abort ASAP
1416 * - ERR_FATAL: we can continue parsing but not start the service
1417 * - ERR_WARN: a warning has been emitted
1418 * - ERR_ALERT: an alert has been emitted
1419 * Only the two first ones can stop processing, the two others are just
1420 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001422int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1423{
1424 static struct peers *curpeers = NULL;
1425 struct peer *newpeer = NULL;
1426 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001427 struct bind_conf *bind_conf;
1428 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001429 int err_code = 0;
1430
1431 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1432
1433 err = invalid_char(args[1]);
1434 if (err) {
1435 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1436 file, linenum, *err, args[0], args[1]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 }
1439
1440 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1441 /*
1442 * If there are two proxies with the same name only following
1443 * combinations are allowed:
1444 */
1445 if (strcmp(curpeers->id, args[1]) == 0) {
1446 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1447 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1448 err_code |= ERR_WARN;
1449 }
1450 }
1451
1452 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1454 err_code |= ERR_ALERT | ERR_ABORT;
1455 goto out;
1456 }
1457
1458 curpeers->next = peers;
1459 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001460 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 curpeers->conf.line = linenum;
1462 curpeers->last_change = now.tv_sec;
1463 curpeers->id = strdup(args[1]);
1464 }
1465 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1466 char *rport, *raddr;
1467 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001468 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001469 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001470
1471 if (!*args[2]) {
1472 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1473 file, linenum, args[0]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
1476 }
1477
1478 err = invalid_char(args[1]);
1479 if (err) {
1480 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1481 file, linenum, *err, args[1]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1488 err_code |= ERR_ALERT | ERR_ABORT;
1489 goto out;
1490 }
1491
1492 /* the peers are linked backwards first */
1493 curpeers->count++;
1494 newpeer->next = curpeers->remote;
1495 curpeers->remote = newpeer;
1496 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001497 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001498 newpeer->conf.line = linenum;
1499
1500 newpeer->last_change = now.tv_sec;
1501 newpeer->id = strdup(args[1]);
1502
1503 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001504 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001505 if (rport) {
1506 *rport++ = 0;
1507 realport = atol(rport);
1508 }
1509 if (!realport) {
1510 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
Willy Tarreaufab5a432011-03-04 15:31:53 +01001515 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001516 free(raddr);
1517 if (!sk) {
1518 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001523 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001524 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001525 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001526
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001527 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001528 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1529 file, linenum, newpeer->addr.ss_family, args[2]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001534 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001535
1536 if (strcmp(newpeer->id, localpeer) == 0) {
1537 /* Current is local peer, it define a frontend */
1538 newpeer->local = 1;
1539
1540 if (!curpeers->peers_fe) {
1541 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1543 err_code |= ERR_ALERT | ERR_ABORT;
1544 goto out;
1545 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001546
Willy Tarreau237250c2011-07-29 01:49:03 +02001547 init_new_proxy(curpeers->peers_fe);
1548 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 curpeers->peers_fe->last_change = now.tv_sec;
1551 curpeers->peers_fe->id = strdup(args[1]);
1552 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001553 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1555 curpeers->peers_fe->timeout.connect = 5000;
1556 curpeers->peers_fe->accept = peer_accept;
1557 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558
1559 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1560
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001561 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1562 if (err_msg && *err_msg) {
1563 indent_msg(&err_msg, 2);
1564 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1565 }
1566 else
1567 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1568 file, linenum, args[0], args[1], args[2]);
1569 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 err_code |= ERR_FATAL;
1571 goto out;
1572 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573
1574 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1575 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1576 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1577 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1578 l->accept = session_accept;
1579 l->handler = process_session;
1580 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1581 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1582 global.maxsock += l->maxconn;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 }
1585 }
1586 } /* neither "peer" nor "peers" */
1587 else if (*args[0] != 0) {
1588 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
1593out:
1594 return err_code;
1595}
1596
1597
Willy Tarreau3842f002009-06-14 11:39:52 +02001598int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599{
1600 static struct proxy *curproxy = NULL;
1601 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001602 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 int rc;
1604 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001605 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001606 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001607 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001608 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001609 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610
Willy Tarreau977b8e42006-12-29 14:19:17 +01001611 if (!strcmp(args[0], "listen"))
1612 rc = PR_CAP_LISTEN;
1613 else if (!strcmp(args[0], "frontend"))
1614 rc = PR_CAP_FE | PR_CAP_RS;
1615 else if (!strcmp(args[0], "backend"))
1616 rc = PR_CAP_BE | PR_CAP_RS;
1617 else if (!strcmp(args[0], "ruleset"))
1618 rc = PR_CAP_RS;
1619 else
1620 rc = PR_CAP_NONE;
1621
1622 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (!*args[1]) {
1624 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1625 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_ABORT;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001630
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001631 err = invalid_char(args[1]);
1632 if (err) {
1633 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1634 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001636 }
1637
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001638 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1639 /*
1640 * If there are two proxies with the same name only following
1641 * combinations are allowed:
1642 *
1643 * listen backend frontend ruleset
1644 * listen - - - -
1645 * backend - - OK -
1646 * frontend - OK - -
1647 * ruleset - - - -
1648 */
1649
1650 if (!strcmp(curproxy->id, args[1]) &&
1651 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1652 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001653 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1654 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1655 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001657 }
1658 }
1659
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001665
Willy Tarreau97cb7802010-01-03 20:23:58 +01001666 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 curproxy->next = proxy;
1668 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001669 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001671 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
1675 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001677 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001678 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001679
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1681
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001682 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1683 if (err_msg && *err_msg) {
1684 indent_msg(&err_msg, 2);
1685 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1686 }
1687 else
1688 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1689 file, linenum, args[0], args[1], args[2]);
1690 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_FATAL;
1692 goto out;
1693 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001694
Willy Tarreau4348fad2012-09-20 16:48:07 +02001695 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001696 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 }
1699
1700 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001701 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001702 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001703
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001706 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001707 curproxy->no_options = defproxy.no_options;
1708 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001709 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001710 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001711 curproxy->except_net = defproxy.except_net;
1712 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001713 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001714 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001716 if (defproxy.fwdfor_hdr_len) {
1717 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1718 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1719 }
1720
Willy Tarreaub86db342009-11-30 11:50:16 +01001721 if (defproxy.orgto_hdr_len) {
1722 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1723 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1724 }
1725
Mark Lamourinec2247f02012-01-04 13:02:01 -05001726 if (defproxy.server_id_hdr_len) {
1727 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1728 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1729 }
1730
Willy Tarreau977b8e42006-12-29 14:19:17 +01001731 if (curproxy->cap & PR_CAP_FE) {
1732 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001733 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001734 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
1736 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001737 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1738 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
1740 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (curproxy->cap & PR_CAP_BE) {
1744 curproxy->fullconn = defproxy.fullconn;
1745 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001747 if (defproxy.check_req) {
1748 curproxy->check_req = calloc(1, defproxy.check_len);
1749 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001753 if (defproxy.expect_str) {
1754 curproxy->expect_str = strdup(defproxy.expect_str);
1755 if (defproxy.expect_regex) {
1756 /* note: this regex is known to be valid */
1757 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1758 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1759 }
1760 }
1761
Willy Tarreau67402132012-05-31 20:40:20 +02001762 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763 if (defproxy.cookie_name)
1764 curproxy->cookie_name = strdup(defproxy.cookie_name);
1765 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001766 if (defproxy.cookie_domain)
1767 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001768
Willy Tarreau31936852010-10-06 16:59:56 +02001769 if (defproxy.cookie_maxidle)
1770 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1771
1772 if (defproxy.cookie_maxlife)
1773 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1774
Emeric Brun647caf12009-06-30 17:57:00 +02001775 if (defproxy.rdp_cookie_name)
1776 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1777 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1778
Willy Tarreau01732802007-11-01 22:48:15 +01001779 if (defproxy.url_param_name)
1780 curproxy->url_param_name = strdup(defproxy.url_param_name);
1781 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001782
Benoitaffb4812009-03-25 13:02:10 +01001783 if (defproxy.hh_name)
1784 curproxy->hh_name = strdup(defproxy.hh_name);
1785 curproxy->hh_len = defproxy.hh_len;
1786 curproxy->hh_match_domain = defproxy.hh_match_domain;
1787
Willy Tarreauef9a3602012-12-08 22:29:20 +01001788 if (defproxy.conn_src.iface_name)
1789 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1790 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1791 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001794 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 if (defproxy.capture_name)
1796 curproxy->capture_name = strdup(defproxy.capture_name);
1797 curproxy->capture_namelen = defproxy.capture_namelen;
1798 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau977b8e42006-12-29 14:19:17 +01001801 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001802 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001803 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001804 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001805 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806 curproxy->uri_auth = defproxy.uri_auth;
1807 curproxy->mon_net = defproxy.mon_net;
1808 curproxy->mon_mask = defproxy.mon_mask;
1809 if (defproxy.monitor_uri)
1810 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1811 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001812 if (defproxy.defbe.name)
1813 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001814
1815 /* get either a pointer to the logformat string or a copy of it */
1816 curproxy->logformat_string = defproxy.logformat_string;
1817 if (curproxy->logformat_string &&
1818 curproxy->logformat_string != default_http_log_format &&
1819 curproxy->logformat_string != default_tcp_log_format &&
1820 curproxy->logformat_string != clf_http_log_format)
1821 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 }
1823
1824 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001825 curproxy->timeout.connect = defproxy.timeout.connect;
1826 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001827 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001828 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001829 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001830 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001831 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001832 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001833 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 }
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001837
1838 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001839 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001840 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001841 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001842 LIST_INIT(&node->list);
1843 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1844 }
1845
Willy Tarreau196729e2012-05-31 19:30:26 +02001846 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1847 if (curproxy->uniqueid_format_string)
1848 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001849
1850 /* copy default header unique id */
1851 if (defproxy.header_unique_id)
1852 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1853
William Lallemand82fe75c2012-10-23 10:25:10 +02001854 /* default compression options */
1855 if (defproxy.comp != NULL) {
1856 curproxy->comp = calloc(1, sizeof(struct comp));
1857 curproxy->comp->algos = defproxy.comp->algos;
1858 curproxy->comp->types = defproxy.comp->types;
1859 }
1860
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001862 curproxy->conf.used_listener_id = EB_ROOT;
1863 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001864
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1868 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001869 /* FIXME-20070101: we should do this too at the end of the
1870 * config parsing to free all default values.
1871 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001872 free(defproxy.check_req);
1873 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001874 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001875 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001876 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001877 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001878 free(defproxy.capture_name);
1879 free(defproxy.monitor_uri);
1880 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001881 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001882 free(defproxy.fwdfor_hdr_name);
1883 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001884 free(defproxy.orgto_hdr_name);
1885 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001886 free(defproxy.server_id_hdr_name);
1887 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001888 free(defproxy.expect_str);
1889 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001890
Willy Tarreau39b06652012-06-01 10:58:06 +02001891 if (defproxy.logformat_string != default_http_log_format &&
1892 defproxy.logformat_string != default_tcp_log_format &&
1893 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001894 free(defproxy.logformat_string);
1895
1896 free(defproxy.uniqueid_format_string);
1897
Willy Tarreaua534fea2008-08-03 12:19:50 +02001898 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001899 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 /* we cannot free uri_auth because it might already be used */
1902 init_default_instance();
1903 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 }
1907 else if (curproxy == NULL) {
1908 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
1912
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913
1914 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001916 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001917 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001918 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001919
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920 if (curproxy == &defproxy) {
1921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_ALERT | ERR_FATAL;
1923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927
Emeric Bruned760922010-10-22 17:59:25 +02001928 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001929 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001934
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001935 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001936 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001937
1938 /* NOTE: the following line might create several listeners if there
1939 * are comma-separated IPs or port ranges. So all further processing
1940 * will have to be applied to all listeners created after last_listen.
1941 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001942 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1943 if (err_msg && *err_msg) {
1944 indent_msg(&err_msg, 2);
1945 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1946 }
1947 else
1948 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1949 file, linenum, args[0], args[1]);
1950 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
1953 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001954
Willy Tarreau4348fad2012-09-20 16:48:07 +02001955 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1956 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001957 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001958 }
1959
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001960 cur_arg = 2;
1961 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001962 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001963 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001964 char *err;
1965
Willy Tarreau26982662012-09-12 23:17:10 +02001966 kw = bind_find_kw(args[cur_arg]);
1967 if (kw) {
1968 char *err = NULL;
1969 int code;
1970
1971 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001972 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1973 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001974 cur_arg += 1 + kw->skip ;
1975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
1977 }
1978
Willy Tarreau4348fad2012-09-20 16:48:07 +02001979 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001980 err_code |= code;
1981
1982 if (code) {
1983 if (err && *err) {
1984 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001985 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001986 }
1987 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001988 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1989 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001990 if (code & ERR_FATAL) {
1991 free(err);
1992 cur_arg += 1 + kw->skip;
1993 goto out;
1994 }
1995 }
1996 free(err);
1997 cur_arg += 1 + kw->skip;
1998 continue;
1999 }
2000
Willy Tarreau8638f482012-09-18 18:01:17 +02002001 err = NULL;
2002 if (!bind_dumped) {
2003 bind_dump_kws(&err);
2004 indent_msg(&err, 4);
2005 bind_dumped = 1;
2006 }
2007
2008 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2009 file, linenum, args[0], args[1], args[cur_arg],
2010 err ? " Registered keywords :" : "", err ? err : "");
2011 free(err);
2012
Willy Tarreau93893792009-07-23 13:19:11 +02002013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002015 }
Willy Tarreau93893792009-07-23 13:19:11 +02002016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 }
2018 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2019 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2020 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_ALERT | ERR_FATAL;
2023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002025 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 /* flush useless bits */
2029 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002032 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
Willy Tarreau1c47f852006-07-09 08:22:27 +02002036 if (!*args[1]) {
2037 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002041 }
2042
Willy Tarreaua534fea2008-08-03 12:19:50 +02002043 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002044 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002045 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002046 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2048
Willy Tarreau93893792009-07-23 13:19:11 +02002049 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2052 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2053 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2054 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2055 else {
2056 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 }
2060 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002061 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002062 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002063
2064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002069 }
2070
2071 if (!*args[1]) {
2072 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002076 }
2077
2078 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002079 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002080
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002081 if (curproxy->uuid <= 0) {
2082 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002083 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086 }
2087
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002088 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2089 if (node) {
2090 struct proxy *target = container_of(node, struct proxy, conf.id);
2091 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2092 file, linenum, proxy_type_str(curproxy), curproxy->id,
2093 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
2096 }
2097 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002098 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002099 else if (!strcmp(args[0], "description")) {
2100 int i, len=0;
2101 char *d;
2102
Cyril Bonté99ed3272010-01-24 23:29:44 +01002103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2105 file, linenum, args[0]);
2106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
2108 }
2109
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002110 if (!*args[1]) {
2111 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2112 file, linenum, args[0]);
2113 return -1;
2114 }
2115
2116 for(i=1; *args[i]; i++)
2117 len += strlen(args[i])+1;
2118
2119 d = (char *)calloc(1, len);
2120 curproxy->desc = d;
2121
2122 d += sprintf(d, "%s", args[1]);
2123 for(i=2; *args[i]; i++)
2124 d += sprintf(d, " %s", args[i]);
2125
2126 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002127 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2128 curproxy->state = PR_STSTOPPED;
2129 }
2130 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2131 curproxy->state = PR_STNEW;
2132 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002133 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2134 int cur_arg = 1;
2135 unsigned int set = 0;
2136
2137 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002138 unsigned int low, high;
2139
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002140 if (strcmp(args[cur_arg], "all") == 0) {
2141 set = 0;
2142 break;
2143 }
2144 else if (strcmp(args[cur_arg], "odd") == 0) {
2145 set |= 0x55555555;
2146 }
2147 else if (strcmp(args[cur_arg], "even") == 0) {
2148 set |= 0xAAAAAAAA;
2149 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002150 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002151 char *dash = strchr(args[cur_arg], '-');
2152
2153 low = high = str2uic(args[cur_arg]);
2154 if (dash)
2155 high = str2uic(dash + 1);
2156
2157 if (high < low) {
2158 unsigned int swap = low;
2159 low = high;
2160 high = swap;
2161 }
2162
2163 if (low < 1 || high > 32) {
2164 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002168 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002169
2170 if (high > global.nbproc) {
2171 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2172 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002174 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002175 while (low <= high)
2176 set |= 1 << (low++ - 1);
2177 }
2178 else {
2179 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2180 file, linenum, args[0]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 }
2184 cur_arg++;
2185 }
2186 curproxy->bind_proc = set;
2187 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002188 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002189 if (curproxy == &defproxy) {
2190 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002193 }
2194
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002195 err = invalid_char(args[1]);
2196 if (err) {
2197 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2198 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002200 }
2201
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002202 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2203 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2204 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002207 }
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2210 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211
Willy Tarreau977b8e42006-12-29 14:19:17 +01002212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 if (*(args[1]) == 0) {
2216 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2217 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002221
Willy Tarreau67402132012-05-31 20:40:20 +02002222 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002223 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002224 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 curproxy->cookie_name = strdup(args[1]);
2227 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 cur_arg = 2;
2230 while (*(args[cur_arg])) {
2231 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002232 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
2234 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002235 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
2237 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002238 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
2240 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002244 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002246 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002252 else if (!strcmp(args[cur_arg], "httponly")) {
2253 curproxy->ck_opts |= PR_CK_HTTPONLY;
2254 }
2255 else if (!strcmp(args[cur_arg], "secure")) {
2256 curproxy->ck_opts |= PR_CK_SECURE;
2257 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002258 else if (!strcmp(args[cur_arg], "domain")) {
2259 if (!*args[cur_arg + 1]) {
2260 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2261 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002264 }
2265
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002266 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002267 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002268 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2269 " dots nor does not start with a dot."
2270 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002271 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002272 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 }
2274
2275 err = invalid_domainchar(args[cur_arg + 1]);
2276 if (err) {
2277 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2278 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 }
2282
Willy Tarreau68a897b2009-12-03 23:28:34 +01002283 if (!curproxy->cookie_domain) {
2284 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2285 } else {
2286 /* one domain was already specified, add another one by
2287 * building the string which will be returned along with
2288 * the cookie.
2289 */
2290 char *new_ptr;
2291 int new_len = strlen(curproxy->cookie_domain) +
2292 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2293 new_ptr = malloc(new_len);
2294 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2295 free(curproxy->cookie_domain);
2296 curproxy->cookie_domain = new_ptr;
2297 }
Willy Tarreau31936852010-10-06 16:59:56 +02002298 cur_arg++;
2299 }
2300 else if (!strcmp(args[cur_arg], "maxidle")) {
2301 unsigned int maxidle;
2302 const char *res;
2303
2304 if (!*args[cur_arg + 1]) {
2305 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2306 file, linenum, args[cur_arg]);
2307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
2309 }
2310
2311 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2312 if (res) {
2313 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2314 file, linenum, *res, args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318 curproxy->cookie_maxidle = maxidle;
2319 cur_arg++;
2320 }
2321 else if (!strcmp(args[cur_arg], "maxlife")) {
2322 unsigned int maxlife;
2323 const char *res;
2324
2325 if (!*args[cur_arg + 1]) {
2326 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2327 file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
2332 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2333 if (res) {
2334 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2335 file, linenum, *res, args[cur_arg]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002340 cur_arg++;
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002343 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 +02002344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
2348 cur_arg++;
2349 }
Willy Tarreau67402132012-05-31 20:40:20 +02002350 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2352 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
2355
Willy Tarreau67402132012-05-31 20:40:20 +02002356 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002361
Willy Tarreau67402132012-05-31 20:40:20 +02002362 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002363 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2364 file, linenum);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002368 else if (!strcmp(args[0], "persist")) { /* persist */
2369 if (*(args[1]) == 0) {
2370 Alert("parsing [%s:%d] : missing persist method.\n",
2371 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002374 }
2375
2376 if (!strncmp(args[1], "rdp-cookie", 10)) {
2377 curproxy->options2 |= PR_O2_RDPC_PRST;
2378
Emeric Brunb982a3d2010-01-04 15:45:53 +01002379 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002380 const char *beg, *end;
2381
2382 beg = args[1] + 11;
2383 end = strchr(beg, ')');
2384
2385 if (!end || end == beg) {
2386 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002390 }
2391
2392 free(curproxy->rdp_cookie_name);
2393 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2394 curproxy->rdp_cookie_len = end-beg;
2395 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002396 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002397 free(curproxy->rdp_cookie_name);
2398 curproxy->rdp_cookie_name = strdup("msts");
2399 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2400 }
2401 else { /* syntax */
2402 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2403 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002406 }
2407 }
2408 else {
2409 Alert("parsing [%s:%d] : unknown persist method.\n",
2410 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002413 }
2414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002416 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002428 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002434 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 curproxy->appsession_name = strdup(args[1]);
2436 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2437 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002438 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2439 if (err) {
2440 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2441 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002444 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002445 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002446
Willy Tarreau51041c72007-09-09 21:56:53 +02002447 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_ABORT;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002452
2453 cur_arg = 6;
2454 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002455 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2456 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002457 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002458 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002459 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002460 } else if (!strcmp(args[cur_arg], "prefix")) {
2461 curproxy->options2 |= PR_O2_AS_PFX;
2462 } else if (!strcmp(args[cur_arg], "mode")) {
2463 if (!*args[cur_arg + 1]) {
2464 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2465 file, linenum, args[0], args[cur_arg]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
2470 cur_arg++;
2471 if (!strcmp(args[cur_arg], "query-string")) {
2472 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2473 curproxy->options2 |= PR_O2_AS_M_QS;
2474 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2475 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2476 curproxy->options2 |= PR_O2_AS_M_PP;
2477 } else {
2478 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
2482 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002483 cur_arg++;
2484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 } /* Url App Session */
2486 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002487 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 if (*(args[4]) == 0) {
2498 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2499 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002503 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 curproxy->capture_name = strdup(args[2]);
2505 curproxy->capture_namelen = strlen(curproxy->capture_name);
2506 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 curproxy->to_log |= LW_COOKIE;
2508 }
2509 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2510 struct cap_hdr *hdr;
2511
2512 if (curproxy == &defproxy) {
2513 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 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
2517
2518 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2519 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2520 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524
2525 hdr = calloc(sizeof(struct cap_hdr), 1);
2526 hdr->next = curproxy->req_cap;
2527 hdr->name = strdup(args[3]);
2528 hdr->namelen = strlen(args[3]);
2529 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002530 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 hdr->index = curproxy->nb_req_cap++;
2532 curproxy->req_cap = hdr;
2533 curproxy->to_log |= LW_REQHDR;
2534 }
2535 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2536 struct cap_hdr *hdr;
2537
2538 if (curproxy == &defproxy) {
2539 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 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
2543
2544 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2545 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2546 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550 hdr = calloc(sizeof(struct cap_hdr), 1);
2551 hdr->next = curproxy->rsp_cap;
2552 hdr->name = strdup(args[3]);
2553 hdr->namelen = strlen(args[3]);
2554 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002555 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 hdr->index = curproxy->nb_rsp_cap++;
2557 curproxy->rsp_cap = hdr;
2558 curproxy->to_log |= LW_RSPHDR;
2559 }
2560 else {
2561 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
2566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002570
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 if (*(args[1]) == 0) {
2572 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 curproxy->conn_retries = atol(args[1]);
2578 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002579 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002580 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002581
2582 if (curproxy == &defproxy) {
2583 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
2586 }
2587
Willy Tarreauff011f22011-01-06 17:51:27 +01002588 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002589 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2590 file, linenum, args[0]);
2591 err_code |= ERR_WARN;
2592 }
2593
Willy Tarreauff011f22011-01-06 17:51:27 +01002594 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002595
Willy Tarreauff011f22011-01-06 17:51:27 +01002596 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002597 err_code |= ERR_ALERT | ERR_ABORT;
2598 goto out;
2599 }
2600
Willy Tarreauff011f22011-01-06 17:51:27 +01002601 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2602 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002603 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002604 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2605 /* set the header name and length into the proxy structure */
2606 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2607 err_code |= ERR_WARN;
2608
2609 if (!*args[1]) {
2610 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2611 file, linenum, args[0]);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615
2616 /* set the desired header name */
2617 free(curproxy->server_id_hdr_name);
2618 curproxy->server_id_hdr_name = strdup(args[1]);
2619 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2620 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002621 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002622 if (curproxy == &defproxy) {
2623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002626 }
2627
Willy Tarreauef6494c2010-01-28 17:12:36 +01002628 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002629 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002633 }
2634
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002635 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2636 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2637 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002640 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002641
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002642 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002643 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002644 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002646 struct redirect_rule *rule;
2647 int cur_arg;
2648 int type = REDIRECT_TYPE_NONE;
2649 int code = 302;
2650 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002651 char *cookie = NULL;
2652 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002653 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002654
Cyril Bonté99ed3272010-01-24 23:29:44 +01002655 if (curproxy == &defproxy) {
2656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
2660
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661 cur_arg = 1;
2662 while (*(args[cur_arg])) {
2663 if (!strcmp(args[cur_arg], "location")) {
2664 if (!*args[cur_arg + 1]) {
2665 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2666 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 }
2670
2671 type = REDIRECT_TYPE_LOCATION;
2672 cur_arg++;
2673 destination = args[cur_arg];
2674 }
2675 else if (!strcmp(args[cur_arg], "prefix")) {
2676 if (!*args[cur_arg + 1]) {
2677 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2678 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002681 }
2682
2683 type = REDIRECT_TYPE_PREFIX;
2684 cur_arg++;
2685 destination = args[cur_arg];
2686 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002687 else if (!strcmp(args[cur_arg], "scheme")) {
2688 if (!*args[cur_arg + 1]) {
2689 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2690 file, linenum, args[0], args[cur_arg]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694
2695 type = REDIRECT_TYPE_SCHEME;
2696 cur_arg++;
2697 destination = args[cur_arg];
2698 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002699 else if (!strcmp(args[cur_arg], "set-cookie")) {
2700 if (!*args[cur_arg + 1]) {
2701 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2702 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002705 }
2706
2707 cur_arg++;
2708 cookie = args[cur_arg];
2709 cookie_set = 1;
2710 }
2711 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2712 if (!*args[cur_arg + 1]) {
2713 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2714 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002717 }
2718
2719 cur_arg++;
2720 cookie = args[cur_arg];
2721 cookie_set = 0;
2722 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002723 else if (!strcmp(args[cur_arg],"code")) {
2724 if (!*args[cur_arg + 1]) {
2725 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002729 }
2730 cur_arg++;
2731 code = atol(args[cur_arg]);
2732 if (code < 301 || code > 303) {
2733 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2734 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002737 }
2738 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002739 else if (!strcmp(args[cur_arg],"drop-query")) {
2740 flags |= REDIRECT_FLAG_DROP_QS;
2741 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002742 else if (!strcmp(args[cur_arg],"append-slash")) {
2743 flags |= REDIRECT_FLAG_APPEND_SLASH;
2744 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002745 else if (strcmp(args[cur_arg], "if") == 0 ||
2746 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002747 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002748 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002749 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2750 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
2753 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002754 break;
2755 }
2756 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002757 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002758 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002761 }
2762 cur_arg++;
2763 }
2764
2765 if (type == REDIRECT_TYPE_NONE) {
2766 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002770 }
2771
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002772 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2773 rule->cond = cond;
2774 rule->rdr_str = strdup(destination);
2775 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002776 if (cookie) {
2777 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002778 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002779 */
2780 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002781 if (cookie_set) {
2782 rule->cookie_str = malloc(rule->cookie_len + 10);
2783 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2784 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2785 rule->cookie_len += 9;
2786 } else {
2787 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002788 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002789 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2790 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002791 }
2792 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002793 rule->type = type;
2794 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002795 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002796 LIST_INIT(&rule->list);
2797 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002798 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2799 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002800 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002801 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002802 struct switching_rule *rule;
2803
Willy Tarreaub099aca2008-10-12 17:26:37 +02002804 if (curproxy == &defproxy) {
2805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002808 }
2809
Willy Tarreau55ea7572007-06-17 19:56:27 +02002810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002812
2813 if (*(args[1]) == 0) {
2814 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002817 }
2818
Willy Tarreauef6494c2010-01-28 17:12:36 +01002819 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002820 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002824 }
2825
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002826 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2827 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2828 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002831 }
2832
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002833 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002834
Willy Tarreau55ea7572007-06-17 19:56:27 +02002835 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2836 rule->cond = cond;
2837 rule->be.name = strdup(args[1]);
2838 LIST_INIT(&rule->list);
2839 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2840 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002841 else if (strcmp(args[0], "use-server") == 0) {
2842 struct server_rule *rule;
2843
2844 if (curproxy == &defproxy) {
2845 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849
2850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2851 err_code |= ERR_WARN;
2852
2853 if (*(args[1]) == 0) {
2854 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858
2859 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2860 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2861 file, linenum, args[0]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
2865
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002866 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2867 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2868 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872
2873 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2874
2875 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2876 rule->cond = cond;
2877 rule->srv.name = strdup(args[1]);
2878 LIST_INIT(&rule->list);
2879 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2880 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2881 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002882 else if ((!strcmp(args[0], "force-persist")) ||
2883 (!strcmp(args[0], "ignore-persist"))) {
2884 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002885
2886 if (curproxy == &defproxy) {
2887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891
2892 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2893 err_code |= ERR_WARN;
2894
Willy Tarreauef6494c2010-01-28 17:12:36 +01002895 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002896 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2897 file, linenum, args[0]);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002902 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2903 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2904 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002909 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002910
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002911 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002912 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002913 if (!strcmp(args[0], "force-persist")) {
2914 rule->type = PERSIST_TYPE_FORCE;
2915 } else {
2916 rule->type = PERSIST_TYPE_IGNORE;
2917 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002918 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002919 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002920 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002921 else if (!strcmp(args[0], "stick-table")) {
2922 int myidx = 1;
2923
Emeric Brun32da3c42010-09-23 18:39:19 +02002924 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 curproxy->table.type = (unsigned int)-1;
2926 while (*args[myidx]) {
2927 const char *err;
2928
2929 if (strcmp(args[myidx], "size") == 0) {
2930 myidx++;
2931 if (!*(args[myidx])) {
2932 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2933 file, linenum, args[myidx-1]);
2934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2938 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2939 file, linenum, *err, args[myidx-1]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002943 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002945 else if (strcmp(args[myidx], "peers") == 0) {
2946 myidx++;
2947 if (!*(args[myidx])) {
2948 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2949 file, linenum, args[myidx-1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 curproxy->table.peers.name = strdup(args[myidx++]);
2954 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002955 else if (strcmp(args[myidx], "expire") == 0) {
2956 myidx++;
2957 if (!*(args[myidx])) {
2958 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2959 file, linenum, args[myidx-1]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2964 if (err) {
2965 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2966 file, linenum, *err, args[myidx-1]);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002971 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 }
2973 else if (strcmp(args[myidx], "nopurge") == 0) {
2974 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002975 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 }
2977 else if (strcmp(args[myidx], "type") == 0) {
2978 myidx++;
2979 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2980 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2981 file, linenum, args[myidx]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002985 /* myidx already points to next arg */
2986 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002987 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002988 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002989 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002990
2991 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002992 nw = args[myidx];
2993 while (*nw) {
2994 /* the "store" keyword supports a comma-separated list */
2995 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002996 sa = NULL; /* store arg */
2997 while (*nw && *nw != ',') {
2998 if (*nw == '(') {
2999 *nw = 0;
3000 sa = ++nw;
3001 while (*nw != ')') {
3002 if (!*nw) {
3003 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3004 file, linenum, args[0], cw);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008 nw++;
3009 }
3010 *nw = '\0';
3011 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003012 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003013 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003014 if (*nw)
3015 *nw++ = '\0';
3016 type = stktable_get_data_type(cw);
3017 if (type < 0) {
3018 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3019 file, linenum, args[0], cw);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
Willy Tarreauac782882010-06-20 10:41:54 +02003023
3024 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3025 switch (err) {
3026 case PE_NONE: break;
3027 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003028 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3029 file, linenum, args[0], cw);
3030 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003031 break;
3032
3033 case PE_ARG_MISSING:
3034 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3035 file, linenum, args[0], cw);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038
3039 case PE_ARG_NOT_USED:
3040 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3041 file, linenum, args[0], cw);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044
3045 default:
3046 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3047 file, linenum, args[0], cw);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003050 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003051 }
3052 myidx++;
3053 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003054 else {
3055 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3056 file, linenum, args[myidx]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 }
3061
3062 if (!curproxy->table.size) {
3063 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3064 file, linenum);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
3068
3069 if (curproxy->table.type == (unsigned int)-1) {
3070 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3071 file, linenum);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075 }
3076 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003077 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003078 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003079 int myidx = 0;
3080 const char *name = NULL;
3081 int flags;
3082
3083 if (curproxy == &defproxy) {
3084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
3088
3089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3090 err_code |= ERR_WARN;
3091 goto out;
3092 }
3093
3094 myidx++;
3095 if ((strcmp(args[myidx], "store") == 0) ||
3096 (strcmp(args[myidx], "store-request") == 0)) {
3097 myidx++;
3098 flags = STK_IS_STORE;
3099 }
3100 else if (strcmp(args[myidx], "store-response") == 0) {
3101 myidx++;
3102 flags = STK_IS_STORE | STK_ON_RSP;
3103 }
3104 else if (strcmp(args[myidx], "match") == 0) {
3105 myidx++;
3106 flags = STK_IS_MATCH;
3107 }
3108 else if (strcmp(args[myidx], "on") == 0) {
3109 myidx++;
3110 flags = STK_IS_MATCH | STK_IS_STORE;
3111 }
3112 else {
3113 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
3118 if (*(args[myidx]) == 0) {
3119 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003124 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003125 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003126 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130
3131 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003132 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003133 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3134 file, linenum, args[0], expr->fetch->kw);
3135 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003136 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003137 goto out;
3138 }
3139 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003140 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003141 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3142 file, linenum, args[0], expr->fetch->kw);
3143 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003144 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003145 goto out;
3146 }
3147 }
3148
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003149 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3150 if (expr->fetch->cap & SMP_CAP_L7)
3151 curproxy->acl_requires |= ACL_USE_L7_ANY;
3152
Emeric Brunb982a3d2010-01-04 15:45:53 +01003153 if (strcmp(args[myidx], "table") == 0) {
3154 myidx++;
3155 name = args[myidx++];
3156 }
3157
Willy Tarreauef6494c2010-01-28 17:12:36 +01003158 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003159 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3160 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3161 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003163 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003164 goto out;
3165 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003167 else if (*(args[myidx])) {
3168 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3169 file, linenum, args[0], args[myidx]);
3170 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003171 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003172 goto out;
3173 }
Emeric Brun97679e72010-09-23 17:56:44 +02003174 if (flags & STK_ON_RSP)
3175 err_code |= warnif_cond_requires_req(cond, file, linenum);
3176 else
3177 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003178
Emeric Brunb982a3d2010-01-04 15:45:53 +01003179 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3180 rule->cond = cond;
3181 rule->expr = expr;
3182 rule->flags = flags;
3183 rule->table.name = name ? strdup(name) : NULL;
3184 LIST_INIT(&rule->list);
3185 if (flags & STK_ON_RSP)
3186 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3187 else
3188 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003193
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3195 curproxy->uri_auth = NULL; /* we must detach from the default config */
3196
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003197 if (!*args[1]) {
3198 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003199 } else if (!strcmp(args[1], "admin")) {
3200 struct stats_admin_rule *rule;
3201
3202 if (curproxy == &defproxy) {
3203 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
3208 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3209 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3210 err_code |= ERR_ALERT | ERR_ABORT;
3211 goto out;
3212 }
3213
3214 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3215 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3216 file, linenum, args[0], args[1]);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003220 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3221 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3222 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
3226
3227 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3228
3229 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3230 rule->cond = cond;
3231 LIST_INIT(&rule->list);
3232 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 } else if (!strcmp(args[1], "uri")) {
3234 if (*(args[2]) == 0) {
3235 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
3243 } else if (!strcmp(args[1], "realm")) {
3244 if (*(args[2]) == 0) {
3245 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003248 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_ABORT;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003253 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003254 unsigned interval;
3255
3256 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3257 if (err) {
3258 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3259 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003262 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003266 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003267 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003268 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003269
3270 if (curproxy == &defproxy) {
3271 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
3274 }
3275
3276 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3277 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3278 err_code |= ERR_ALERT | ERR_ABORT;
3279 goto out;
3280 }
3281
Willy Tarreauff011f22011-01-06 17:51:27 +01003282 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3283 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003284 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3285 file, linenum, args[0]);
3286 err_code |= ERR_WARN;
3287 }
3288
Willy Tarreauff011f22011-01-06 17:51:27 +01003289 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003290
Willy Tarreauff011f22011-01-06 17:51:27 +01003291 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
3295
Willy Tarreauff011f22011-01-06 17:51:27 +01003296 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3297 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003298
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 } else if (!strcmp(args[1], "auth")) {
3300 if (*(args[2]) == 0) {
3301 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3305 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_ABORT;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
3309 } else if (!strcmp(args[1], "scope")) {
3310 if (*(args[2]) == 0) {
3311 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_ABORT;
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
3319 } else if (!strcmp(args[1], "enable")) {
3320 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_ABORT;
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003325 } else if (!strcmp(args[1], "hide-version")) {
3326 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_ABORT;
3329 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003330 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003331 } else if (!strcmp(args[1], "show-legends")) {
3332 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3333 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3334 err_code |= ERR_ALERT | ERR_ABORT;
3335 goto out;
3336 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003337 } else if (!strcmp(args[1], "show-node")) {
3338
3339 if (*args[2]) {
3340 int i;
3341 char c;
3342
3343 for (i=0; args[2][i]; i++) {
3344 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003345 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3346 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003347 break;
3348 }
3349
3350 if (!i || args[2][i]) {
3351 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3352 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3353 file, linenum, args[0], args[1]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
3357 }
3358
3359 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3360 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3361 err_code |= ERR_ALERT | ERR_ABORT;
3362 goto out;
3363 }
3364 } else if (!strcmp(args[1], "show-desc")) {
3365 char *desc = NULL;
3366
3367 if (*args[2]) {
3368 int i, len=0;
3369 char *d;
3370
3371 for(i=2; *args[i]; i++)
3372 len += strlen(args[i])+1;
3373
3374 desc = d = (char *)calloc(1, len);
3375
3376 d += sprintf(d, "%s", args[2]);
3377 for(i=3; *args[i]; i++)
3378 d += sprintf(d, " %s", args[i]);
3379 }
3380
3381 if (!*args[2] && !global.desc)
3382 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3383 file, linenum, args[1]);
3384 else {
3385 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3386 free(desc);
3387 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3388 err_code |= ERR_ALERT | ERR_ABORT;
3389 goto out;
3390 }
3391 free(desc);
3392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003394stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003395 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 +01003396 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 }
3401 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402 int optnum;
3403
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003404 if (*(args[1]) == '\0') {
3405 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3406 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003410
3411 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3412 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003413 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3414 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3415 file, linenum, cfg_opts[optnum].name);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
Willy Tarreau93893792009-07-23 13:19:11 +02003419 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3420 err_code |= ERR_WARN;
3421 goto out;
3422 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003423
Willy Tarreau3842f002009-06-14 11:39:52 +02003424 curproxy->no_options &= ~cfg_opts[optnum].val;
3425 curproxy->options &= ~cfg_opts[optnum].val;
3426
3427 switch (kwm) {
3428 case KWM_STD:
3429 curproxy->options |= cfg_opts[optnum].val;
3430 break;
3431 case KWM_NO:
3432 curproxy->no_options |= cfg_opts[optnum].val;
3433 break;
3434 case KWM_DEF: /* already cleared */
3435 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003436 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003437
Willy Tarreau93893792009-07-23 13:19:11 +02003438 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003439 }
3440 }
3441
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003442 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3443 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003444 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3445 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3446 file, linenum, cfg_opts2[optnum].name);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
Willy Tarreau93893792009-07-23 13:19:11 +02003450 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3451 err_code |= ERR_WARN;
3452 goto out;
3453 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003454
Willy Tarreau3842f002009-06-14 11:39:52 +02003455 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3456 curproxy->options2 &= ~cfg_opts2[optnum].val;
3457
3458 switch (kwm) {
3459 case KWM_STD:
3460 curproxy->options2 |= cfg_opts2[optnum].val;
3461 break;
3462 case KWM_NO:
3463 curproxy->no_options2 |= cfg_opts2[optnum].val;
3464 break;
3465 case KWM_DEF: /* already cleared */
3466 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003467 }
Willy Tarreau93893792009-07-23 13:19:11 +02003468 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003469 }
3470 }
3471
Willy Tarreau3842f002009-06-14 11:39:52 +02003472 if (kwm != KWM_STD) {
3473 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003474 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003477 }
3478
Emeric Brun3a058f32009-06-30 18:26:00 +02003479 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003480 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003482 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003483 if (*(args[2]) != '\0') {
3484 if (!strcmp(args[2], "clf")) {
3485 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003486 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003487 } else {
3488 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003491 }
3492 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003493 if (curproxy->logformat_string != default_http_log_format &&
3494 curproxy->logformat_string != default_tcp_log_format &&
3495 curproxy->logformat_string != clf_http_log_format)
3496 free(curproxy->logformat_string);
3497 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003498 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003499 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003501 if (curproxy->logformat_string != default_http_log_format &&
3502 curproxy->logformat_string != default_tcp_log_format &&
3503 curproxy->logformat_string != clf_http_log_format)
3504 free(curproxy->logformat_string);
3505 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 else if (!strcmp(args[1], "tcpka")) {
3508 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003509 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003511
3512 if (curproxy->cap & PR_CAP_FE)
3513 curproxy->options |= PR_O_TCP_CLI_KA;
3514 if (curproxy->cap & PR_CAP_BE)
3515 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
3520
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003522 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003523 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003524 curproxy->options2 &= ~PR_O2_CHK_ANY;
3525 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 if (!*args[2]) { /* no argument */
3527 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3528 curproxy->check_len = strlen(DEF_CHECK_REQ);
3529 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003530 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 curproxy->check_req = (char *)malloc(reqlen);
3532 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003533 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003535 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (*args[4])
3537 reqlen += strlen(args[4]);
3538 else
3539 reqlen += strlen("HTTP/1.0");
3540
3541 curproxy->check_req = (char *)malloc(reqlen);
3542 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003543 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003545 }
3546 else if (!strcmp(args[1], "ssl-hello-chk")) {
3547 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550
Willy Tarreaua534fea2008-08-03 12:19:50 +02003551 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003552 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003553 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003554 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 }
Willy Tarreau23677902007-05-08 23:50:35 +02003556 else if (!strcmp(args[1], "smtpchk")) {
3557 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003558 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
3561 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003562
3563 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3564 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3565 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3566 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3567 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3568 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3569 curproxy->check_req = (char *)malloc(reqlen);
3570 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3571 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3572 } else {
3573 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3574 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3575 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3576 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3577 }
3578 }
3579 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003580 else if (!strcmp(args[1], "pgsql-check")) {
3581 /* use PostgreSQL request to check servers' health */
3582 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3583 err_code |= ERR_WARN;
3584
3585 free(curproxy->check_req);
3586 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003587 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003588 curproxy->options2 |= PR_O2_PGSQL_CHK;
3589
3590 if (*(args[2])) {
3591 int cur_arg = 2;
3592
3593 while (*(args[cur_arg])) {
3594 if (strcmp(args[cur_arg], "user") == 0) {
3595 char * packet;
3596 uint32_t packet_len;
3597 uint32_t pv;
3598
3599 /* suboption header - needs additional argument for it */
3600 if (*(args[cur_arg+1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3602 file, linenum, args[0], args[1], args[cur_arg]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606
3607 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3608 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3609 pv = htonl(0x30000); /* protocol version 3.0 */
3610
3611 packet = (char*) calloc(1, packet_len);
3612
3613 memcpy(packet + 4, &pv, 4);
3614
3615 /* copy "user" */
3616 memcpy(packet + 8, "user", 4);
3617
3618 /* copy username */
3619 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3620
3621 free(curproxy->check_req);
3622 curproxy->check_req = packet;
3623 curproxy->check_len = packet_len;
3624
3625 packet_len = htonl(packet_len);
3626 memcpy(packet, &packet_len, 4);
3627 cur_arg += 2;
3628 } else {
3629 /* unknown suboption - catchall */
3630 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3631 file, linenum, args[0], args[1]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 } /* end while loop */
3636 }
3637 }
3638
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003639 else if (!strcmp(args[1], "redis-check")) {
3640 /* use REDIS PING request to check servers' health */
3641 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3642 err_code |= ERR_WARN;
3643
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003647 curproxy->options2 |= PR_O2_REDIS_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3652 }
3653
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 else if (!strcmp(args[1], "mysql-check")) {
3655 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3657 err_code |= ERR_WARN;
3658
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003661 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003662 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003663
3664 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3665 * const char mysql40_client_auth_pkt[] = {
3666 * "\x0e\x00\x00" // packet length
3667 * "\x01" // packet number
3668 * "\x00\x00" // client capabilities
3669 * "\x00\x00\x01" // max packet
3670 * "haproxy\x00" // username (null terminated string)
3671 * "\x00" // filler (always 0x00)
3672 * "\x01\x00\x00" // packet length
3673 * "\x00" // packet number
3674 * "\x01" // COM_QUIT command
3675 * };
3676 */
3677
3678 if (*(args[2])) {
3679 int cur_arg = 2;
3680
3681 while (*(args[cur_arg])) {
3682 if (strcmp(args[cur_arg], "user") == 0) {
3683 char *mysqluser;
3684 int packetlen, reqlen, userlen;
3685
3686 /* suboption header - needs additional argument for it */
3687 if (*(args[cur_arg+1]) == 0) {
3688 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3689 file, linenum, args[0], args[1], args[cur_arg]);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693 mysqluser = args[cur_arg + 1];
3694 userlen = strlen(mysqluser);
3695 packetlen = userlen + 7;
3696 reqlen = packetlen + 9;
3697
3698 free(curproxy->check_req);
3699 curproxy->check_req = (char *)calloc(1, reqlen);
3700 curproxy->check_len = reqlen;
3701
3702 snprintf(curproxy->check_req, 4, "%c%c%c",
3703 ((unsigned char) packetlen & 0xff),
3704 ((unsigned char) (packetlen >> 8) & 0xff),
3705 ((unsigned char) (packetlen >> 16) & 0xff));
3706
3707 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003708 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003709 curproxy->check_req[8] = 1;
3710 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3711 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3712 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3713 cur_arg += 2;
3714 } else {
3715 /* unknown suboption - catchall */
3716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3717 file, linenum, args[0], args[1]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 } /* end while loop */
3722 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003723 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003724 else if (!strcmp(args[1], "ldap-check")) {
3725 /* use LDAP request to check servers' health */
3726 free(curproxy->check_req);
3727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003729 curproxy->options2 |= PR_O2_LDAP_CHK;
3730
3731 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3732 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3733 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3734 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003735 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003736 int cur_arg;
3737
3738 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3739 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003740 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003741
Willy Tarreau87cf5142011-08-19 22:57:24 +02003742 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003743
3744 free(curproxy->fwdfor_hdr_name);
3745 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3746 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3747
3748 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3749 cur_arg = 2;
3750 while (*(args[cur_arg])) {
3751 if (!strcmp(args[cur_arg], "except")) {
3752 /* suboption except - needs additional argument for it */
3753 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3754 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3755 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003758 }
3759 /* flush useless bits */
3760 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003761 cur_arg += 2;
3762 } else if (!strcmp(args[cur_arg], "header")) {
3763 /* suboption header - needs additional argument for it */
3764 if (*(args[cur_arg+1]) == 0) {
3765 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003769 }
3770 free(curproxy->fwdfor_hdr_name);
3771 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3772 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3773 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003774 } else if (!strcmp(args[cur_arg], "if-none")) {
3775 curproxy->options &= ~PR_O_FF_ALWAYS;
3776 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003777 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003778 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003779 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003780 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003783 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003784 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003785 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003786 else if (!strcmp(args[1], "originalto")) {
3787 int cur_arg;
3788
3789 /* insert x-original-to field, but not for the IP address listed as an except.
3790 * set default options (ie: bitfield, header name, etc)
3791 */
3792
3793 curproxy->options |= PR_O_ORGTO;
3794
3795 free(curproxy->orgto_hdr_name);
3796 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3797 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3798
Willy Tarreau87cf5142011-08-19 22:57:24 +02003799 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003800 cur_arg = 2;
3801 while (*(args[cur_arg])) {
3802 if (!strcmp(args[cur_arg], "except")) {
3803 /* suboption except - needs additional argument for it */
3804 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3805 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3806 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003809 }
3810 /* flush useless bits */
3811 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3812 cur_arg += 2;
3813 } else if (!strcmp(args[cur_arg], "header")) {
3814 /* suboption header - needs additional argument for it */
3815 if (*(args[cur_arg+1]) == 0) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3817 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003820 }
3821 free(curproxy->orgto_hdr_name);
3822 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3823 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3824 cur_arg += 2;
3825 } else {
3826 /* unknown suboption - catchall */
3827 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3828 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003831 }
3832 } /* end while loop */
3833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 else {
3835 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
Willy Tarreau93893792009-07-23 13:19:11 +02003839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003841 else if (!strcmp(args[0], "default_backend")) {
3842 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003844
3845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003849 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003850 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003851 curproxy->defbe.name = strdup(args[1]);
3852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003856
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003857 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3858 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 /* enable reconnections to dispatch */
3861 curproxy->options |= PR_O_REDISP;
3862 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003863 else if (!strcmp(args[0], "http-check")) {
3864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003866
3867 if (strcmp(args[1], "disable-on-404") == 0) {
3868 /* enable a graceful server shutdown on an HTTP 404 response */
3869 curproxy->options |= PR_O_DISABLE404;
3870 }
Willy Tarreauef781042010-01-27 11:53:01 +01003871 else if (strcmp(args[1], "send-state") == 0) {
3872 /* enable emission of the apparent state of a server in HTTP checks */
3873 curproxy->options2 |= PR_O2_CHK_SNDST;
3874 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003875 else if (strcmp(args[1], "expect") == 0) {
3876 const char *ptr_arg;
3877 int cur_arg;
3878
3879 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3880 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884
3885 cur_arg = 2;
3886 /* consider exclamation marks, sole or at the beginning of a word */
3887 while (*(ptr_arg = args[cur_arg])) {
3888 while (*ptr_arg == '!') {
3889 curproxy->options2 ^= PR_O2_EXP_INV;
3890 ptr_arg++;
3891 }
3892 if (*ptr_arg)
3893 break;
3894 cur_arg++;
3895 }
3896 /* now ptr_arg points to the beginning of a word past any possible
3897 * exclamation mark, and cur_arg is the argument which holds this word.
3898 */
3899 if (strcmp(ptr_arg, "status") == 0) {
3900 if (!*(args[cur_arg + 1])) {
3901 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3902 file, linenum, args[0], args[1], ptr_arg);
3903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
3905 }
3906 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003907 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003908 curproxy->expect_str = strdup(args[cur_arg + 1]);
3909 }
3910 else if (strcmp(ptr_arg, "string") == 0) {
3911 if (!*(args[cur_arg + 1])) {
3912 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3913 file, linenum, args[0], args[1], ptr_arg);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003918 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003919 curproxy->expect_str = strdup(args[cur_arg + 1]);
3920 }
3921 else if (strcmp(ptr_arg, "rstatus") == 0) {
3922 if (!*(args[cur_arg + 1])) {
3923 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3924 file, linenum, args[0], args[1], ptr_arg);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003929 free(curproxy->expect_str);
3930 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3931 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003932 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3933 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3934 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3935 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
3938 }
3939 }
3940 else if (strcmp(ptr_arg, "rstring") == 0) {
3941 if (!*(args[cur_arg + 1])) {
3942 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3943 file, linenum, args[0], args[1], ptr_arg);
3944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
3946 }
3947 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003948 free(curproxy->expect_str);
3949 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3950 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003951 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3952 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3953 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3954 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 }
3959 else {
3960 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3961 file, linenum, args[0], args[1], ptr_arg);
3962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
3964 }
3965 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003966 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003967 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 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003970 }
3971 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003972 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003973 if (curproxy == &defproxy) {
3974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003977 }
3978
Willy Tarreaub80c2302007-11-30 20:51:32 +01003979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003981
3982 if (strcmp(args[1], "fail") == 0) {
3983 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003984 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003985 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3986 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003989 }
3990
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3992 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3993 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003996 }
3997 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3998 }
3999 else {
4000 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004003 }
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005#ifdef TPROXY
4006 else if (!strcmp(args[0], "transparent")) {
4007 /* enable transparent proxy connections */
4008 curproxy->options |= PR_O_TRANSP;
4009 }
4010#endif
4011 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004012 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004014
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 if (*(args[1]) == 0) {
4016 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
4020 curproxy->maxconn = atol(args[1]);
4021 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004022 else if (!strcmp(args[0], "backlog")) { /* backlog */
4023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004025
4026 if (*(args[1]) == 0) {
4027 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004030 }
4031 curproxy->backlog = atol(args[1]);
4032 }
Willy Tarreau86034312006-12-29 00:10:33 +01004033 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004036
Willy Tarreau86034312006-12-29 00:10:33 +01004037 if (*(args[1]) == 0) {
4038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004041 }
4042 curproxy->fullconn = atol(args[1]);
4043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4045 if (*(args[1]) == 0) {
4046 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004050 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4051 if (err) {
4052 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4053 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004056 }
4057 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 }
4059 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004060 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 if (curproxy == &defproxy) {
4062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004066 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004068
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 if (strchr(args[1], ':') == NULL) {
4070 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004074 sk = str2sa(args[1]);
4075 if (!sk) {
4076 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004081 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 }
4083 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004084 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004085 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004086
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004087 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4088 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004092 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004093 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4094 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4095 err_code |= ERR_WARN;
4096
4097 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4098 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4099 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4100 }
4101 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4102 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4103 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4104 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004105 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4106 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4107 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4108 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004109 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004110 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
4114 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004115 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004117 char *rport, *raddr;
4118 short realport = 0;
4119 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004126 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128
4129 if (!*args[2]) {
4130 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004135
4136 err = invalid_char(args[1]);
4137 if (err) {
4138 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4139 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004142 }
4143
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004144 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004145 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004146
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004147 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4149 err_code |= ERR_ALERT | ERR_ABORT;
4150 goto out;
4151 }
4152
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 /* the servers are linked backwards first */
4154 newsrv->next = curproxy->srv;
4155 curproxy->srv = newsrv;
4156 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004157 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004158 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004160 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004161 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004162 LIST_INIT(&newsrv->pendconns);
4163 do_check = 0;
4164 newsrv->state = SRV_RUNNING; /* early server setup */
4165 newsrv->last_change = now.tv_sec;
4166 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004168 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004169 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004170 * - IP: => port=+0, relative
4171 * - IP:N => port=N, absolute
4172 * - IP:+N => port=+N, relative
4173 * - IP:-N => port=-N, relative
4174 */
4175 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004176 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004177 if (rport) {
4178 *rport++ = 0;
4179 realport = atol(rport);
4180 if (!isdigit((unsigned char)*rport))
4181 newsrv->state |= SRV_MAPPORTS;
4182 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004184
Willy Tarreaufab5a432011-03-04 15:31:53 +01004185 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004187 if (!sk) {
4188 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
4191 }
4192 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004193 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4194 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004195
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004196 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004197 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4198 file, linenum, newsrv->addr.ss_family, args[2]);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004202 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004203
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004204 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004205 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004206 newsrv->inter = curproxy->defsrv.inter;
4207 newsrv->fastinter = curproxy->defsrv.fastinter;
4208 newsrv->downinter = curproxy->defsrv.downinter;
4209 newsrv->rise = curproxy->defsrv.rise;
4210 newsrv->fall = curproxy->defsrv.fall;
4211 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4212 newsrv->minconn = curproxy->defsrv.minconn;
4213 newsrv->maxconn = curproxy->defsrv.maxconn;
4214 newsrv->slowstart = curproxy->defsrv.slowstart;
4215 newsrv->onerror = curproxy->defsrv.onerror;
4216 newsrv->consecutive_errors_limit
4217 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004218#ifdef OPENSSL
4219 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4220#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004221 newsrv->uweight = newsrv->iweight
4222 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004224 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226 cur_arg = 3;
4227 } else {
4228 newsrv = &curproxy->defsrv;
4229 cur_arg = 1;
4230 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004231
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004233 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 newsrv->cookie = strdup(args[cur_arg + 1]);
4235 newsrv->cklen = strlen(args[cur_arg + 1]);
4236 cur_arg += 2;
4237 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004238 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004239 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4240 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4241 cur_arg += 2;
4242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004244 if (!*args[cur_arg + 1]) {
4245 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4246 file, linenum, args[cur_arg]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004252 if (newsrv->rise <= 0) {
4253 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4254 file, linenum, args[cur_arg]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
Willy Tarreau96839092010-03-29 10:02:24 +02004259 if (newsrv->health)
4260 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 cur_arg += 2;
4262 }
4263 else if (!strcmp(args[cur_arg], "fall")) {
4264 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004265
4266 if (!*args[cur_arg + 1]) {
4267 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4268 file, linenum, args[cur_arg]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
4273 if (newsrv->fall <= 0) {
4274 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4275 file, linenum, args[cur_arg]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 cur_arg += 2;
4281 }
4282 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004283 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4284 if (err) {
4285 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4286 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004289 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004290 if (val <= 0) {
4291 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4292 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004295 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004296 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 cur_arg += 2;
4298 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004299 else if (!strcmp(args[cur_arg], "fastinter")) {
4300 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4301 if (err) {
4302 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4303 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004306 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004307 if (val <= 0) {
4308 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4309 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004312 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004313 newsrv->fastinter = val;
4314 cur_arg += 2;
4315 }
4316 else if (!strcmp(args[cur_arg], "downinter")) {
4317 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4318 if (err) {
4319 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4320 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004323 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004324 if (val <= 0) {
4325 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4326 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004329 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004330 newsrv->downinter = val;
4331 cur_arg += 2;
4332 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004333 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004334 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004335 if (!sk) {
4336 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004340 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004341 cur_arg += 2;
4342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004343 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004344 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 cur_arg += 2;
4346 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004347 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348 newsrv->state |= SRV_BACKUP;
4349 cur_arg ++;
4350 }
Simon Hormanfa461682011-06-25 09:39:49 +09004351 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4352 newsrv->state |= SRV_NON_STICK;
4353 cur_arg ++;
4354 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4356 newsrv->state |= SRV_SEND_PROXY;
4357 cur_arg ++;
4358 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004359 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4360 newsrv->check.send_proxy = 1;
4361 cur_arg ++;
4362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 else if (!strcmp(args[cur_arg], "weight")) {
4364 int w;
4365 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004366 if (w < 0 || w > 256) {
4367 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004372 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 cur_arg += 2;
4374 }
4375 else if (!strcmp(args[cur_arg], "minconn")) {
4376 newsrv->minconn = atol(args[cur_arg + 1]);
4377 cur_arg += 2;
4378 }
4379 else if (!strcmp(args[cur_arg], "maxconn")) {
4380 newsrv->maxconn = atol(args[cur_arg + 1]);
4381 cur_arg += 2;
4382 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004383 else if (!strcmp(args[cur_arg], "maxqueue")) {
4384 newsrv->maxqueue = atol(args[cur_arg + 1]);
4385 cur_arg += 2;
4386 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004387 else if (!strcmp(args[cur_arg], "slowstart")) {
4388 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004389 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004390 if (err) {
4391 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4392 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004395 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004396 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004397 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4398 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004401 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004402 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004403 cur_arg += 2;
4404 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004405 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004406
4407 if (!*args[cur_arg + 1]) {
4408 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4409 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004412 }
4413
4414 newsrv->trackit = strdup(args[cur_arg + 1]);
4415
4416 cur_arg += 2;
4417 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004418 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 global.maxsock++;
4420 do_check = 1;
4421 cur_arg += 1;
4422 }
Willy Tarreau96839092010-03-29 10:02:24 +02004423 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4424 newsrv->state |= SRV_MAINTAIN;
4425 newsrv->state &= ~SRV_RUNNING;
4426 newsrv->health = 0;
4427 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004428 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004429 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004430 if (!strcmp(args[cur_arg + 1], "none"))
4431 newsrv->observe = HANA_OBS_NONE;
4432 else if (!strcmp(args[cur_arg + 1], "layer4"))
4433 newsrv->observe = HANA_OBS_LAYER4;
4434 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4435 if (curproxy->mode != PR_MODE_HTTP) {
4436 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4437 file, linenum, args[cur_arg + 1]);
4438 err_code |= ERR_ALERT;
4439 }
4440 newsrv->observe = HANA_OBS_LAYER7;
4441 }
4442 else {
4443 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004444 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004445 file, linenum, args[cur_arg], args[cur_arg + 1]);
4446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
4448 }
4449
4450 cur_arg += 2;
4451 }
4452 else if (!strcmp(args[cur_arg], "on-error")) {
4453 if (!strcmp(args[cur_arg + 1], "fastinter"))
4454 newsrv->onerror = HANA_ONERR_FASTINTER;
4455 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4456 newsrv->onerror = HANA_ONERR_FAILCHK;
4457 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4458 newsrv->onerror = HANA_ONERR_SUDDTH;
4459 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4460 newsrv->onerror = HANA_ONERR_MARKDWN;
4461 else {
4462 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004463 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004464 file, linenum, args[cur_arg], args[cur_arg + 1]);
4465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
4467 }
4468
4469 cur_arg += 2;
4470 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004471 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4472 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4473 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4474 else {
4475 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4476 file, linenum, args[cur_arg], args[cur_arg + 1]);
4477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
4479 }
4480
4481 cur_arg += 2;
4482 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004483 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4484 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4485 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4486 else {
4487 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4488 file, linenum, args[cur_arg], args[cur_arg + 1]);
4489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
4491 }
4492
4493 cur_arg += 2;
4494 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004495 else if (!strcmp(args[cur_arg], "error-limit")) {
4496 if (!*args[cur_arg + 1]) {
4497 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4498 file, linenum, args[cur_arg]);
4499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
4501 }
4502
4503 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4504
4505 if (newsrv->consecutive_errors_limit <= 0) {
4506 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4507 file, linenum, args[cur_arg]);
4508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
4510 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004511 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004512 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004513 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004514 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004515 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004516
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004518 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4519 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004523 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004524 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4525 if (!sk) {
4526 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004530 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004531
4532 if (port_low != port_high) {
4533 int i;
4534 if (port_low <= 0 || port_low > 65535 ||
4535 port_high <= 0 || port_high > 65535 ||
4536 port_low > port_high) {
4537 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4538 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004541 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004542 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4543 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4544 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004545 }
4546
Willy Tarreaubaaee002006-06-26 02:48:02 +02004547 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004548 while (*(args[cur_arg])) {
4549 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004550#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4551#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004552 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004553 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4554 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004557 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004558#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004559 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004560 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004561 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004564 }
4565 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004566 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4567 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004568 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004569 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4570 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004571 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4572 char *name, *end;
4573
4574 name = args[cur_arg+1] + 7;
4575 while (isspace(*name))
4576 name++;
4577
4578 end = name;
4579 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4580 end++;
4581
Willy Tarreauef9a3602012-12-08 22:29:20 +01004582 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4583 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4584 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4585 newsrv->conn_src.bind_hdr_len = end - name;
4586 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4587 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4588 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004589
4590 /* now look for an occurrence number */
4591 while (isspace(*end))
4592 end++;
4593 if (*end == ',') {
4594 end++;
4595 name = end;
4596 if (*end == '-')
4597 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004598 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004599 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004600 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004601 }
4602
Willy Tarreauef9a3602012-12-08 22:29:20 +01004603 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004604 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4605 " occurrences values smaller than %d.\n",
4606 file, linenum, MAX_HDR_HISTORY);
4607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004610 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004611 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004612 if (!sk) {
4613 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004617 newsrv->conn_src.tproxy_addr = *sk;
4618 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004619 }
4620 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004621#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004622 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004623#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004624 cur_arg += 2;
4625 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004626#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004627 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004628 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004631#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4632 } /* "usesrc" */
4633
4634 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4635#ifdef SO_BINDTODEVICE
4636 if (!*args[cur_arg + 1]) {
4637 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4638 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004641 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004642 free(newsrv->conn_src.iface_name);
4643 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4644 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004645 global.last_checks |= LSTCHK_NETADM;
4646#else
4647 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4648 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004651#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004652 cur_arg += 2;
4653 continue;
4654 }
4655 /* this keyword in not an option of "source" */
4656 break;
4657 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004659 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004660 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4661 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004666 static int srv_dumped;
4667 struct srv_kw *kw;
4668 char *err;
4669
4670 kw = srv_find_kw(args[cur_arg]);
4671 if (kw) {
4672 char *err = NULL;
4673 int code;
4674
4675 if (!kw->parse) {
4676 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4677 file, linenum, args[0], args[1], args[cur_arg]);
4678 cur_arg += 1 + kw->skip ;
4679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
4681 }
4682
4683 if (defsrv && !kw->default_ok) {
4684 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4685 file, linenum, args[0], args[1], args[cur_arg]);
4686 cur_arg += 1 + kw->skip ;
4687 err_code |= ERR_ALERT;
4688 continue;
4689 }
4690
4691 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4692 err_code |= code;
4693
4694 if (code) {
4695 if (err && *err) {
4696 indent_msg(&err, 2);
4697 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4698 }
4699 else
4700 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4701 file, linenum, args[0], args[1], args[cur_arg]);
4702 if (code & ERR_FATAL) {
4703 free(err);
4704 cur_arg += 1 + kw->skip;
4705 goto out;
4706 }
4707 }
4708 free(err);
4709 cur_arg += 1 + kw->skip;
4710 continue;
4711 }
4712
4713 err = NULL;
4714 if (!srv_dumped) {
4715 srv_dump_kws(&err);
4716 indent_msg(&err, 4);
4717 srv_dumped = 1;
4718 }
4719
4720 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4721 file, linenum, args[0], args[1], args[cur_arg],
4722 err ? " Registered keywords :" : "", err ? err : "");
4723 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004724
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 }
4728 }
4729
4730 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004731 if (newsrv->trackit) {
4732 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4733 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004736 }
4737
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004738 /* If neither a port nor an addr was specified and no check transport
4739 * layer is forced, then the transport layer used by the checks is the
4740 * same as for the production traffic. Otherwise we use raw_sock by
4741 * default, unless one is specified.
4742 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004743 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004744#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004745 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004746#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004747 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4748 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004749 /* try to get the port from check.addr if check.port not set */
4750 if (!newsrv->check.port)
4751 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004752
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004753 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4754 newsrv->check.port = realport; /* by default */
4755 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004756 /* not yet valid, because no port was set on
4757 * the server either. We'll check if we have
4758 * a known port on the first listener.
4759 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004760 struct listener *l;
4761
4762 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004763 newsrv->check.port = get_host_port(&l->addr);
4764 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004765 break;
4766 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004767 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004768 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4770 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004774
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004775 /* Allocate buffer for check requests... */
4776 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004777 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4778 err_code |= ERR_ALERT | ERR_ABORT;
4779 goto out;
4780 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004781 newsrv->check.bi->size = global.tune.chksize;
4782
4783 /* Allocate buffer for check responses... */
4784 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4785 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4786 err_code |= ERR_ALERT | ERR_ABORT;
4787 goto out;
4788 }
4789 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004790
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004791 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004792 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004793 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4794 err_code |= ERR_ALERT | ERR_ABORT;
4795 goto out;
4796 }
4797
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004798 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4799 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 newsrv->state |= SRV_CHECKED;
4801 }
4802
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004803 if (!defsrv) {
4804 if (newsrv->state & SRV_BACKUP)
4805 curproxy->srv_bck++;
4806 else
4807 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004808
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004809 newsrv->prev_state = newsrv->state;
4810 }
William Lallemanda73203e2012-03-12 12:48:57 +01004811 }
4812
4813 else if (strcmp(args[0], "unique-id-format") == 0) {
4814 if (!*(args[1])) {
4815 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
4818 }
William Lallemand3203ff42012-11-11 17:30:56 +01004819 if (*(args[2])) {
4820 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004824 free(curproxy->uniqueid_format_string);
4825 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004826 }
William Lallemanda73203e2012-03-12 12:48:57 +01004827
4828 else if (strcmp(args[0], "unique-id-header") == 0) {
4829 if (!*(args[1])) {
4830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
4834 free(curproxy->header_unique_id);
4835 curproxy->header_unique_id = strdup(args[1]);
4836 }
4837
William Lallemand723b73a2012-02-08 16:37:49 +01004838 else if (strcmp(args[0], "log-format") == 0) {
4839 if (!*(args[1])) {
4840 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
William Lallemand3203ff42012-11-11 17:30:56 +01004844 if (*(args[2])) {
4845 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
4848 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004849
4850 if (curproxy->logformat_string != default_http_log_format &&
4851 curproxy->logformat_string != default_tcp_log_format &&
4852 curproxy->logformat_string != clf_http_log_format)
4853 free(curproxy->logformat_string);
4854 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
William Lallemand723b73a2012-02-08 16:37:49 +01004856
William Lallemand0f99e342011-10-12 17:50:54 +02004857 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4858 /* delete previous herited or defined syslog servers */
4859 struct logsrv *back;
4860
4861 if (*(args[1]) != 0) {
4862 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866
William Lallemand723b73a2012-02-08 16:37:49 +01004867 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4868 LIST_DEL(&tmplogsrv->list);
4869 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004870 }
4871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004873 struct logsrv *logsrv;
4874
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004876 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004877 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004878 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004879 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004880 LIST_INIT(&node->list);
4881 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004883 }
4884 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004885
4886 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887
William Lallemand0f99e342011-10-12 17:50:54 +02004888 logsrv->facility = get_log_facility(args[2]);
4889 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895
William Lallemand0f99e342011-10-12 17:50:54 +02004896 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004898 logsrv->level = get_log_level(args[3]);
4899 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
4903
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
4905 }
4906
William Lallemand0f99e342011-10-12 17:50:54 +02004907 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004908 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004909 logsrv->minlvl = get_log_level(args[4]);
4910 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004911 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004915 }
4916 }
4917
Robert Tsai81ae1952007-12-05 10:47:29 +01004918 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004919 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004920 if (!sk) {
4921 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004922 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
William Lallemand0f99e342011-10-12 17:50:54 +02004926 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004927 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004928 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004929 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004930 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
4933 }
William Lallemand0f99e342011-10-12 17:50:54 +02004934 logsrv->addr = *sk;
4935 if (!get_host_port(&logsrv->addr))
4936 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
William Lallemand0f99e342011-10-12 17:50:54 +02004938
4939 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 }
4941 else {
4942 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4943 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 }
4948 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004949 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004950 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004951
Willy Tarreau977b8e42006-12-29 14:19:17 +01004952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004954
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004956 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4957 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004961
4962 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004963 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4964 free(curproxy->conn_src.iface_name);
4965 curproxy->conn_src.iface_name = NULL;
4966 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004967
Willy Tarreaud5191e72010-02-09 20:50:45 +01004968 sk = str2sa(args[1]);
4969 if (!sk) {
4970 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
4973 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004974 curproxy->conn_src.source_addr = *sk;
4975 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004976
4977 cur_arg = 2;
4978 while (*(args[cur_arg])) {
4979 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004980#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4981#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004982 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004983 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4984 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004987 }
4988#endif
4989 if (!*args[cur_arg + 1]) {
4990 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4991 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004994 }
4995
4996 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004997 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4998 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004999 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005000 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5001 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005002 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5003 char *name, *end;
5004
5005 name = args[cur_arg+1] + 7;
5006 while (isspace(*name))
5007 name++;
5008
5009 end = name;
5010 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5011 end++;
5012
Willy Tarreauef9a3602012-12-08 22:29:20 +01005013 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5014 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5015 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5016 curproxy->conn_src.bind_hdr_len = end - name;
5017 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5018 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5019 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005020
5021 /* now look for an occurrence number */
5022 while (isspace(*end))
5023 end++;
5024 if (*end == ',') {
5025 end++;
5026 name = end;
5027 if (*end == '-')
5028 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005029 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005030 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005031 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005032 }
5033
Willy Tarreauef9a3602012-12-08 22:29:20 +01005034 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005035 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5036 " occurrences values smaller than %d.\n",
5037 file, linenum, MAX_HDR_HISTORY);
5038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
5040 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005042 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005043 if (!sk) {
5044 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005048 curproxy->conn_src.tproxy_addr = *sk;
5049 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005050 }
5051 global.last_checks |= LSTCHK_NETADM;
5052#if !defined(CONFIG_HAP_LINUX_TPROXY)
5053 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005054#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005055#else /* no TPROXY support */
5056 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005057 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060#endif
5061 cur_arg += 2;
5062 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005063 }
5064
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5066#ifdef SO_BINDTODEVICE
5067 if (!*args[cur_arg + 1]) {
5068 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005072 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005073 free(curproxy->conn_src.iface_name);
5074 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5075 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 global.last_checks |= LSTCHK_NETADM;
5077#else
5078 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5079 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005082#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005083 cur_arg += 2;
5084 continue;
5085 }
5086 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005087 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005092 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5093 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5094 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105
5106 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005107 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005108 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
5112 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005114 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005115 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
5119 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005121 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005128 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005129 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
5133 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005135 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005136 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005140 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005142 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005143 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005145 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005146 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005147 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005150 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005153 }
5154 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005156 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005157 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168
5169 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005170 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005171 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005177 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005178 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
5182 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005184 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005185 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
5189 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005191 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005192 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
5196 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005198 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005199 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005203 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005205 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005206 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005208 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005211 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005212
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 if (curproxy == &defproxy) {
5214 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005218 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 if (*(args[1]) == 0) {
5222 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005226
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005227 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005228 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5229 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5230 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
5233 }
5234 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5235 }
5236 else if (*args[2]) {
5237 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5238 file, linenum, args[0], args[2]);
5239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241 }
5242
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005243 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005244 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005245 wl->s = strdup(args[1]);
5246 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005247 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
5249 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005255 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005256
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005258 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005259 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
5263 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005265 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005266 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 }
5270 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005272 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005273 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
5277 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 }
5284
Willy Tarreauade5ec42010-01-28 19:33:49 +01005285 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005286 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005287 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290 }
5291 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005292 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005293 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005294 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 }
5298 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005299 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005300 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005301 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005302 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
5305 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005306 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005307
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if (curproxy == &defproxy) {
5309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005313 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 if (*(args[1]) == 0) {
5317 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 }
5321
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005322 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005323 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5324 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5325 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
5329 err_code |= warnif_cond_requires_req(cond, file, linenum);
5330 }
5331 else if (*args[2]) {
5332 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5333 file, linenum, args[0], args[2]);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005338 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005339 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005340 wl->s = strdup(args[1]);
5341 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 }
5343 else if (!strcmp(args[0], "errorloc") ||
5344 !strcmp(args[0], "errorloc302") ||
5345 !strcmp(args[0], "errorloc303")) { /* error location */
5346 int errnum, errlen;
5347 char *err;
5348
Willy Tarreau977b8e42006-12-29 14:19:17 +01005349 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005353 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357
5358 errnum = atol(args[1]);
5359 if (!strcmp(args[0], "errorloc303")) {
5360 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5361 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5362 } else {
5363 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5364 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5365 }
5366
Willy Tarreau0f772532006-12-23 20:51:41 +01005367 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5368 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005369 chunk_destroy(&curproxy->errmsg[rc]);
5370 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005371 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005374
5375 if (rc >= HTTP_ERR_SIZE) {
5376 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5377 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 free(err);
5379 }
5380 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005381 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5382 int errnum, errlen, fd;
5383 char *err;
5384 struct stat stat;
5385
5386 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005388
5389 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005390 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005393 }
5394
5395 fd = open(args[2], O_RDONLY);
5396 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5397 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5398 file, linenum, args[2], args[1]);
5399 if (fd >= 0)
5400 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005403 }
5404
Willy Tarreau27a674e2009-08-17 07:23:33 +02005405 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005406 errlen = stat.st_size;
5407 } else {
5408 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005409 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005410 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005411 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005412 }
5413
5414 err = malloc(errlen); /* malloc() must succeed during parsing */
5415 errnum = read(fd, err, errlen);
5416 if (errnum != errlen) {
5417 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5418 file, linenum, args[2], args[1]);
5419 close(fd);
5420 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005423 }
5424 close(fd);
5425
5426 errnum = atol(args[1]);
5427 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5428 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005429 chunk_destroy(&curproxy->errmsg[rc]);
5430 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005431 break;
5432 }
5433 }
5434
5435 if (rc >= HTTP_ERR_SIZE) {
5436 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5437 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005438 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005439 free(err);
5440 }
5441 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005442 else if (!strcmp(args[0], "compression")) {
5443 struct comp *comp;
5444 if (curproxy->comp == NULL) {
5445 comp = calloc(1, sizeof(struct comp));
5446 curproxy->comp = comp;
5447 } else {
5448 comp = curproxy->comp;
5449 }
5450
5451 if (!strcmp(args[1], "algo")) {
5452 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005453 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005454
William Lallemand82fe75c2012-10-23 10:25:10 +02005455 cur_arg = 2;
5456 if (!*args[cur_arg]) {
5457 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5458 file, linenum, args[0]);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462 while (*(args[cur_arg])) {
5463 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5464 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5465 file, linenum, args[0], args[cur_arg]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
William Lallemand552df672012-11-07 13:21:47 +01005469 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5470 curproxy->comp->algos->end(&ctx);
5471 } else {
5472 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5473 file, linenum, args[0], args[cur_arg]);
5474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
5476 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005477 cur_arg ++;
5478 continue;
5479 }
5480 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005481 else if (!strcmp(args[1], "offload")) {
5482 comp->offload = 1;
5483 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005484 else if (!strcmp(args[1], "type")) {
5485 int cur_arg;
5486 cur_arg = 2;
5487 if (!*args[cur_arg]) {
5488 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5489 file, linenum, args[0]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493 while (*(args[cur_arg])) {
5494 comp_append_type(comp, args[cur_arg]);
5495 cur_arg ++;
5496 continue;
5497 }
5498 }
5499 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005500 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005501 file, linenum, args[0]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
5505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005507 struct cfg_kw_list *kwl;
5508 int index;
5509
5510 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5511 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5512 if (kwl->kw[index].section != CFG_LISTEN)
5513 continue;
5514 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5515 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005516 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005517 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005518 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005521 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005522 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005523 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005524 err_code |= ERR_WARN;
5525 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005526 }
Willy Tarreau93893792009-07-23 13:19:11 +02005527 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005528 }
5529 }
5530 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005531
Willy Tarreau6daf3432008-01-22 16:44:08 +01005532 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 }
Willy Tarreau93893792009-07-23 13:19:11 +02005536 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005537 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005538 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539}
5540
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005541int
5542cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5543{
5544
5545 int err_code = 0;
5546 const char *err;
5547
5548 if (!strcmp(args[0], "userlist")) { /* new userlist */
5549 struct userlist *newul;
5550
5551 if (!*args[1]) {
5552 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5553 file, linenum, args[0]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557
5558 err = invalid_char(args[1]);
5559 if (err) {
5560 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5561 file, linenum, *err, args[0], args[1]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565
5566 for (newul = userlist; newul; newul = newul->next)
5567 if (!strcmp(newul->name, args[1])) {
5568 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5569 file, linenum, args[1]);
5570 err_code |= ERR_WARN;
5571 goto out;
5572 }
5573
5574 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5575 if (!newul) {
5576 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5577 err_code |= ERR_ALERT | ERR_ABORT;
5578 goto out;
5579 }
5580
5581 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5582 newul->name = strdup(args[1]);
5583
5584 if (!newul->groupusers | !newul->name) {
5585 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5586 err_code |= ERR_ALERT | ERR_ABORT;
5587 goto out;
5588 }
5589
5590 newul->next = userlist;
5591 userlist = newul;
5592
5593 } else if (!strcmp(args[0], "group")) { /* new group */
5594 int cur_arg, i;
5595 const char *err;
5596
5597 if (!*args[1]) {
5598 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5599 file, linenum, args[0]);
5600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
5603
5604 err = invalid_char(args[1]);
5605 if (err) {
5606 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5607 file, linenum, *err, args[0], args[1]);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611
5612 for(i = 0; i < userlist->grpcnt; i++)
5613 if (!strcmp(userlist->groups[i], args[1])) {
5614 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5615 file, linenum, args[1], userlist->name);
5616 err_code |= ERR_ALERT;
5617 goto out;
5618 }
5619
5620 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5621 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5622 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
5626
5627 cur_arg = 2;
5628
5629 while (*args[cur_arg]) {
5630 if (!strcmp(args[cur_arg], "users")) {
5631 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5632 cur_arg += 2;
5633 continue;
5634 } else {
5635 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5636 file, linenum, args[0]);
5637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
5640 }
5641
5642 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5643 } else if (!strcmp(args[0], "user")) { /* new user */
5644 struct auth_users *newuser;
5645 int cur_arg;
5646
5647 if (!*args[1]) {
5648 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5649 file, linenum, args[0]);
5650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
5652 }
5653
5654 for (newuser = userlist->users; newuser; newuser = newuser->next)
5655 if (!strcmp(newuser->user, args[1])) {
5656 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5657 file, linenum, args[1], userlist->name);
5658 err_code |= ERR_ALERT;
5659 goto out;
5660 }
5661
5662 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5663 if (!newuser) {
5664 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5665 err_code |= ERR_ALERT | ERR_ABORT;
5666 goto out;
5667 }
5668
5669 newuser->user = strdup(args[1]);
5670
5671 newuser->next = userlist->users;
5672 userlist->users = newuser;
5673
5674 cur_arg = 2;
5675
5676 while (*args[cur_arg]) {
5677 if (!strcmp(args[cur_arg], "password")) {
5678#ifndef CONFIG_HAP_CRYPT
5679 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5680 file, linenum);
5681 err_code |= ERR_ALERT;
5682#endif
5683 newuser->pass = strdup(args[cur_arg + 1]);
5684 cur_arg += 2;
5685 continue;
5686 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5687 newuser->pass = strdup(args[cur_arg + 1]);
5688 newuser->flags |= AU_O_INSECURE;
5689 cur_arg += 2;
5690 continue;
5691 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005692 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 cur_arg += 2;
5694 continue;
5695 } else {
5696 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5697 file, linenum, args[0]);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
5701 }
5702 } else {
5703 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5704 err_code |= ERR_ALERT | ERR_FATAL;
5705 }
5706
5707out:
5708 return err_code;
5709}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710
5711/*
5712 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005713 * Returns the error code, 0 if OK, or any combination of :
5714 * - ERR_ABORT: must abort ASAP
5715 * - ERR_FATAL: we can continue parsing but not start the service
5716 * - ERR_WARN: a warning has been emitted
5717 * - ERR_ALERT: an alert has been emitted
5718 * Only the two first ones can stop processing, the two others are just
5719 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005721int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005723 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 FILE *f;
5725 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005727 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 if ((f=fopen(file,"r")) == NULL)
5730 return -1;
5731
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005732 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005733 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005734 char *end;
5735 char *args[MAX_LINE_ARGS + 1];
5736 char *line = thisline;
5737
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 linenum++;
5739
5740 end = line + strlen(line);
5741
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005742 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5743 /* Check if we reached the limit and the last char is not \n.
5744 * Watch out for the last line without the terminating '\n'!
5745 */
5746 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005747 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005749 }
5750
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005752 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 line++;
5754
5755 arg = 0;
5756 args[arg] = line;
5757
5758 while (*line && arg < MAX_LINE_ARGS) {
5759 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5760 * C equivalent value. Other combinations left unchanged (eg: \1).
5761 */
5762 if (*line == '\\') {
5763 int skip = 0;
5764 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5765 *line = line[1];
5766 skip = 1;
5767 }
5768 else if (line[1] == 'r') {
5769 *line = '\r';
5770 skip = 1;
5771 }
5772 else if (line[1] == 'n') {
5773 *line = '\n';
5774 skip = 1;
5775 }
5776 else if (line[1] == 't') {
5777 *line = '\t';
5778 skip = 1;
5779 }
5780 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005781 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 unsigned char hex1, hex2;
5783 hex1 = toupper(line[2]) - '0';
5784 hex2 = toupper(line[3]) - '0';
5785 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5786 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5787 *line = (hex1<<4) + hex2;
5788 skip = 3;
5789 }
5790 else {
5791 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005792 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 }
5794 }
5795 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005796 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 end -= skip;
5798 }
5799 line++;
5800 }
5801 else if (*line == '#' || *line == '\n' || *line == '\r') {
5802 /* end of string, end of loop */
5803 *line = 0;
5804 break;
5805 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005806 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005808 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005809 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 line++;
5811 args[++arg] = line;
5812 }
5813 else {
5814 line++;
5815 }
5816 }
5817
5818 /* empty line */
5819 if (!**args)
5820 continue;
5821
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005822 if (*line) {
5823 /* we had to stop due to too many args.
5824 * Let's terminate the string, print the offending part then cut the
5825 * last arg.
5826 */
5827 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5828 line++;
5829 *line = '\0';
5830
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005831 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005832 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005833 err_code |= ERR_ALERT | ERR_FATAL;
5834 args[arg] = line;
5835 }
5836
Willy Tarreau540abe42007-05-02 20:50:16 +02005837 /* zero out remaining args and ensure that at least one entry
5838 * is zeroed out.
5839 */
5840 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 args[arg] = line;
5842 }
5843
Willy Tarreau3842f002009-06-14 11:39:52 +02005844 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005845 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005846 char *tmp;
5847
Willy Tarreau3842f002009-06-14 11:39:52 +02005848 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005849 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005850 for (arg=0; *args[arg+1]; arg++)
5851 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005852 *tmp = '\0'; // fix the next arg to \0
5853 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005854 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005855 else if (!strcmp(args[0], "default")) {
5856 kwm = KWM_DEF;
5857 for (arg=0; *args[arg+1]; arg++)
5858 args[arg] = args[arg+1]; // shift args after inversion
5859 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005860
William Lallemand0f99e342011-10-12 17:50:54 +02005861 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5862 strcmp(args[0], "log") != 0) {
5863 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005864 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005865 }
5866
Willy Tarreau977b8e42006-12-29 14:19:17 +01005867 if (!strcmp(args[0], "listen") ||
5868 !strcmp(args[0], "frontend") ||
5869 !strcmp(args[0], "backend") ||
5870 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005871 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005873 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005874 cursection = strdup(args[0]);
5875 }
5876 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005878 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005879 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005880 }
5881 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005882 confsect = CFG_USERLIST;
5883 free(cursection);
5884 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005885 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005886 else if (!strcmp(args[0], "peers")) {
5887 confsect = CFG_PEERS;
5888 free(cursection);
5889 cursection = strdup(args[0]);
5890 }
5891
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 /* else it's a section keyword */
5893
5894 switch (confsect) {
5895 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005896 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 break;
5898 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005899 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005901 case CFG_USERLIST:
5902 err_code |= cfg_parse_users(file, linenum, args, kwm);
5903 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005904 case CFG_PEERS:
5905 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5906 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005908 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005909 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005911
5912 if (err_code & ERR_ABORT)
5913 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005915 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005916 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005918 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005919}
5920
Willy Tarreaubb925012009-07-23 13:36:36 +02005921/*
5922 * Returns the error code, 0 if OK, or any combination of :
5923 * - ERR_ABORT: must abort ASAP
5924 * - ERR_FATAL: we can continue parsing but not start the service
5925 * - ERR_WARN: a warning has been emitted
5926 * - ERR_ALERT: an alert has been emitted
5927 * Only the two first ones can stop processing, the two others are just
5928 * indicators.
5929 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005930int check_config_validity()
5931{
5932 int cfgerr = 0;
5933 struct proxy *curproxy = NULL;
5934 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005935 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005936 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005937 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005938 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005940 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 /*
5942 * Now, check for the integrity of all that we have collected.
5943 */
5944
5945 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005946 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947
Willy Tarreau193b8c62012-11-22 00:17:38 +01005948 if (!global.tune.max_http_hdr)
5949 global.tune.max_http_hdr = MAX_HTTP_HDR;
5950
5951 if (!global.tune.cookie_len)
5952 global.tune.cookie_len = CAPTURE_LEN;
5953
5954 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5955
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005956 /* first, we will invert the proxy list order */
5957 curproxy = NULL;
5958 while (proxy) {
5959 struct proxy *next;
5960
5961 next = proxy->next;
5962 proxy->next = curproxy;
5963 curproxy = proxy;
5964 if (!next)
5965 break;
5966 proxy = next;
5967 }
5968
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005970 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005971 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005972 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005973 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005974 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005975 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005976 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005977
Willy Tarreau050536d2012-10-04 08:47:34 +02005978 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005979 /* proxy ID not set, use automatic numbering with first
5980 * spare entry starting with next_pxid.
5981 */
5982 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5983 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5984 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005985 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005986 next_pxid++;
5987
Willy Tarreau55ea7572007-06-17 19:56:27 +02005988
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005990 /* ensure we don't keep listeners uselessly bound */
5991 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 curproxy = curproxy->next;
5993 continue;
5994 }
5995
Willy Tarreau16a21472012-11-19 12:39:59 +01005996 /* number of processes this proxy is bound to */
5997 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5998
Willy Tarreauff01a212009-03-15 13:46:16 +01005999 switch (curproxy->mode) {
6000 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006001 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006002 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006003 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6004 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006005 cfgerr++;
6006 }
6007
6008 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006009 Warning("config : servers will be ignored for %s '%s'.\n",
6010 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006011 break;
6012
6013 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006014 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006015 break;
6016
6017 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006018 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006019 break;
6020 }
6021
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006022 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006023 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006024 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006025 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6026 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006027 cfgerr++;
6028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006030 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006031 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6032 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006033 cfgerr++;
6034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006036 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006037 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6038 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006039 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006040 }
6041 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006042 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006043 /* If no LB algo is set in a backend, and we're not in
6044 * transparent mode, dispatch mode nor proxy mode, we
6045 * want to use balance roundrobin by default.
6046 */
6047 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6048 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 }
6050 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006051
Willy Tarreau1620ec32011-08-06 17:05:02 +02006052 if (curproxy->options & PR_O_DISPATCH)
6053 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6054 else if (curproxy->options & PR_O_HTTP_PROXY)
6055 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6056 else if (curproxy->options & PR_O_TRANSP)
6057 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006058
Willy Tarreau1620ec32011-08-06 17:05:02 +02006059 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6060 if (curproxy->options & PR_O_DISABLE404) {
6061 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6062 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6063 err_code |= ERR_WARN;
6064 curproxy->options &= ~PR_O_DISABLE404;
6065 }
6066 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6067 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6068 "send-state", proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
6070 curproxy->options &= ~PR_O2_CHK_SNDST;
6071 }
Willy Tarreauef781042010-01-27 11:53:01 +01006072 }
6073
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006074 /* if a default backend was specified, let's find it */
6075 if (curproxy->defbe.name) {
6076 struct proxy *target;
6077
Alex Williams96532db2009-11-01 21:27:13 -05006078 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006079 if (!target) {
6080 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6081 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006082 cfgerr++;
6083 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006084 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6085 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006086 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006087 } else {
6088 free(curproxy->defbe.name);
6089 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006090 /* we force the backend to be present on at least all of
6091 * the frontend's processes.
6092 */
6093 target->bind_proc = curproxy->bind_proc ?
6094 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006095
6096 /* Emit a warning if this proxy also has some servers */
6097 if (curproxy->srv) {
6098 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6099 curproxy->id);
6100 err_code |= ERR_WARN;
6101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 }
6103 }
6104
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006105 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006106 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6107 /* map jump target for ACT_SETBE in req_rep chain */
6108 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006109 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006110 struct proxy *target;
6111
Willy Tarreaua496b602006-12-17 23:15:24 +01006112 if (exp->action != ACT_SETBE)
6113 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006114
Alex Williams96532db2009-11-01 21:27:13 -05006115 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006116 if (!target) {
6117 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6118 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006119 cfgerr++;
6120 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006121 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6122 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006123 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006124 } else {
6125 free((void *)exp->replace);
6126 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006127 /* we force the backend to be present on at least all of
6128 * the frontend's processes.
6129 */
6130 target->bind_proc = curproxy->bind_proc ?
6131 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006132 }
6133 }
6134 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006135
6136 /* find the target proxy for 'use_backend' rules */
6137 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006138 struct proxy *target;
6139
Alex Williams96532db2009-11-01 21:27:13 -05006140 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006141
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006142 if (!target) {
6143 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6144 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006145 cfgerr++;
6146 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006147 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6148 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006149 cfgerr++;
6150 } else {
6151 free((void *)rule->be.name);
6152 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006153 /* we force the backend to be present on at least all of
6154 * the frontend's processes.
6155 */
6156 target->bind_proc = curproxy->bind_proc ?
6157 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006158 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006159 }
6160
6161 /* find the target proxy for 'use_backend' rules */
6162 list_for_each_entry(srule, &curproxy->server_rules, list) {
6163 struct server *target = findserver(curproxy, srule->srv.name);
6164
6165 if (!target) {
6166 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6167 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6168 cfgerr++;
6169 continue;
6170 }
6171 free((void *)srule->srv.name);
6172 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006173 }
6174
Emeric Brunb982a3d2010-01-04 15:45:53 +01006175 /* find the target table for 'stick' rules */
6176 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6177 struct proxy *target;
6178
Emeric Brun1d33b292010-01-04 15:47:17 +01006179 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6180 if (mrule->flags & STK_IS_STORE)
6181 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6182
Emeric Brunb982a3d2010-01-04 15:45:53 +01006183 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006184 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006185 else
6186 target = curproxy;
6187
6188 if (!target) {
6189 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6190 curproxy->id, mrule->table.name);
6191 cfgerr++;
6192 }
6193 else if (target->table.size == 0) {
6194 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6195 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6196 cfgerr++;
6197 }
Willy Tarreau12785782012-04-27 21:37:17 +02006198 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6199 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006200 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6201 cfgerr++;
6202 }
6203 else {
6204 free((void *)mrule->table.name);
6205 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006206 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006207 }
6208 }
6209
6210 /* find the target table for 'store response' rules */
6211 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6212 struct proxy *target;
6213
Emeric Brun1d33b292010-01-04 15:47:17 +01006214 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6215
Emeric Brunb982a3d2010-01-04 15:45:53 +01006216 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006217 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006218 else
6219 target = curproxy;
6220
6221 if (!target) {
6222 Alert("Proxy '%s': unable to find store table '%s'.\n",
6223 curproxy->id, mrule->table.name);
6224 cfgerr++;
6225 }
6226 else if (target->table.size == 0) {
6227 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6228 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6229 cfgerr++;
6230 }
Willy Tarreau12785782012-04-27 21:37:17 +02006231 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6232 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006233 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6234 cfgerr++;
6235 }
6236 else {
6237 free((void *)mrule->table.name);
6238 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006239 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006240 }
6241 }
6242
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006243 /* find the target table for 'tcp-request' layer 4 rules */
6244 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6245 struct proxy *target;
6246
Willy Tarreau56123282010-08-06 19:06:56 +02006247 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006248 continue;
6249
6250 if (trule->act_prm.trk_ctr.table.n)
6251 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6252 else
6253 target = curproxy;
6254
6255 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006256 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6257 curproxy->id, trule->act_prm.trk_ctr.table.n,
6258 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006259 cfgerr++;
6260 }
6261 else if (target->table.size == 0) {
6262 Alert("Proxy '%s': table '%s' used but not configured.\n",
6263 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6264 cfgerr++;
6265 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006266 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6267 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6268 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6269 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6270 cfgerr++;
6271 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006272 else {
6273 free(trule->act_prm.trk_ctr.table.n);
6274 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006275 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006276 * to pass a list of counters to track and allocate them right here using
6277 * stktable_alloc_data_type().
6278 */
6279 }
6280 }
6281
Willy Tarreaud1f96522010-08-03 19:34:32 +02006282 /* find the target table for 'tcp-request' layer 6 rules */
6283 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6284 struct proxy *target;
6285
Willy Tarreau56123282010-08-06 19:06:56 +02006286 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006287 continue;
6288
6289 if (trule->act_prm.trk_ctr.table.n)
6290 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6291 else
6292 target = curproxy;
6293
6294 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006295 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6296 curproxy->id, trule->act_prm.trk_ctr.table.n,
6297 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006298 cfgerr++;
6299 }
6300 else if (target->table.size == 0) {
6301 Alert("Proxy '%s': table '%s' used but not configured.\n",
6302 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6303 cfgerr++;
6304 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006305 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6306 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6307 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6308 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6309 cfgerr++;
6310 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006311 else {
6312 free(trule->act_prm.trk_ctr.table.n);
6313 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006314 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006315 * to pass a list of counters to track and allocate them right here using
6316 * stktable_alloc_data_type().
6317 */
6318 }
6319 }
6320
Emeric Brun32da3c42010-09-23 18:39:19 +02006321 if (curproxy->table.peers.name) {
6322 struct peers *curpeers = peers;
6323
6324 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6325 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6326 free((void *)curproxy->table.peers.name);
6327 curproxy->table.peers.p = peers;
6328 break;
6329 }
6330 }
6331
6332 if (!curpeers) {
6333 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6334 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006335 free((void *)curproxy->table.peers.name);
6336 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006337 cfgerr++;
6338 }
6339 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006340 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6341 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006342 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006343 cfgerr++;
6344 }
6345 }
6346
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006347 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006348 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006349 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6350 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6351 "proxy", curproxy->id);
6352 cfgerr++;
6353 goto out_uri_auth_compat;
6354 }
6355
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006356 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006357 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006358 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006359 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006360
Willy Tarreau95fa4692010-02-01 13:05:50 +01006361 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6362 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006363
6364 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006365 uri_auth_compat_req[i++] = "realm";
6366 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6367 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006368
Willy Tarreau95fa4692010-02-01 13:05:50 +01006369 uri_auth_compat_req[i++] = "unless";
6370 uri_auth_compat_req[i++] = "{";
6371 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6372 uri_auth_compat_req[i++] = "}";
6373 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006374
Willy Tarreauff011f22011-01-06 17:51:27 +01006375 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6376 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006377 cfgerr++;
6378 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006379 }
6380
Willy Tarreauff011f22011-01-06 17:51:27 +01006381 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006382
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006383 if (curproxy->uri_auth->auth_realm) {
6384 free(curproxy->uri_auth->auth_realm);
6385 curproxy->uri_auth->auth_realm = NULL;
6386 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006387
6388 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389 }
6390out_uri_auth_compat:
6391
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006392 cfgerr += acl_find_targets(curproxy);
6393
Willy Tarreau2738a142006-07-08 17:28:09 +02006394 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006395 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006396 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006397 (!curproxy->timeout.connect ||
6398 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006399 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006400 " | While not properly invalid, you will certainly encounter various problems\n"
6401 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006402 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006403 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006404 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006405 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006406
Willy Tarreau1fa31262007-12-03 00:36:16 +01006407 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6408 * We must still support older configurations, so let's find out whether those
6409 * parameters have been set or must be copied from contimeouts.
6410 */
6411 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006412 if (!curproxy->timeout.tarpit ||
6413 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006414 /* tarpit timeout not set. We search in the following order:
6415 * default.tarpit, curr.connect, default.connect.
6416 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006417 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006418 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006419 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006420 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006421 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006422 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006423 }
6424 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 (!curproxy->timeout.queue ||
6426 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006427 /* queue timeout not set. We search in the following order:
6428 * default.queue, curr.connect, default.connect.
6429 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006430 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006431 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006432 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006433 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006434 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006435 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006436 }
6437 }
6438
Willy Tarreau1620ec32011-08-06 17:05:02 +02006439 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006440 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6441 curproxy->check_req = (char *)malloc(curproxy->check_len);
6442 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006443 }
6444
Willy Tarreau193b8c62012-11-22 00:17:38 +01006445 /* ensure that cookie capture length is not too large */
6446 if (curproxy->capture_len >= global.tune.cookie_len) {
6447 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6448 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6449 err_code |= ERR_WARN;
6450 curproxy->capture_len = global.tune.cookie_len - 1;
6451 }
6452
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006453 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006454 if (curproxy->nb_req_cap) {
6455 if (curproxy->mode == PR_MODE_HTTP) {
6456 curproxy->req_cap_pool = create_pool("ptrcap",
6457 curproxy->nb_req_cap * sizeof(char *),
6458 MEM_F_SHARED);
6459 } else {
6460 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6461 proxy_type_str(curproxy), curproxy->id);
6462 err_code |= ERR_WARN;
6463 curproxy->to_log &= ~LW_REQHDR;
6464 curproxy->nb_req_cap = 0;
6465 }
6466 }
6467
6468 if (curproxy->nb_rsp_cap) {
6469 if (curproxy->mode == PR_MODE_HTTP) {
6470 curproxy->rsp_cap_pool = create_pool("ptrcap",
6471 curproxy->nb_rsp_cap * sizeof(char *),
6472 MEM_F_SHARED);
6473 } else {
6474 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6475 proxy_type_str(curproxy), curproxy->id);
6476 err_code |= ERR_WARN;
6477 curproxy->to_log &= ~LW_REQHDR;
6478 curproxy->nb_rsp_cap = 0;
6479 }
6480 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006481
Willy Tarreau196729e2012-05-31 19:30:26 +02006482 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006483 if (!(curproxy->cap & PR_CAP_FE)) {
6484 if (curproxy->logformat_string != default_http_log_format &&
6485 curproxy->logformat_string != default_tcp_log_format &&
6486 curproxy->logformat_string != clf_http_log_format)
6487 free(curproxy->logformat_string);
6488 curproxy->logformat_string = NULL;
6489 }
6490
Willy Tarreau196729e2012-05-31 19:30:26 +02006491 if (curproxy->logformat_string)
6492 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6493
6494 if (curproxy->uniqueid_format_string)
6495 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6496
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 /* first, we will invert the servers list order */
6498 newsrv = NULL;
6499 while (curproxy->srv) {
6500 struct server *next;
6501
6502 next = curproxy->srv->next;
6503 curproxy->srv->next = newsrv;
6504 newsrv = curproxy->srv;
6505 if (!next)
6506 break;
6507 curproxy->srv = next;
6508 }
6509
Willy Tarreaudd701652010-05-25 23:03:02 +02006510 /* assign automatic UIDs to servers which don't have one yet */
6511 next_id = 1;
6512 newsrv = curproxy->srv;
6513 while (newsrv != NULL) {
6514 if (!newsrv->puid) {
6515 /* server ID not set, use automatic numbering with first
6516 * spare entry starting with next_svid.
6517 */
6518 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6519 newsrv->conf.id.key = newsrv->puid = next_id;
6520 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6521 }
6522 next_id++;
6523 newsrv = newsrv->next;
6524 }
6525
Willy Tarreau20697042007-11-15 23:26:18 +01006526 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006527 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006528
Willy Tarreau62c3be22012-01-20 13:12:32 +01006529 /*
6530 * If this server supports a maxconn parameter, it needs a dedicated
6531 * tasks to fill the emptied slots when a connection leaves.
6532 * Also, resolve deferred tracking dependency if needed.
6533 */
6534 newsrv = curproxy->srv;
6535 while (newsrv != NULL) {
6536 if (newsrv->minconn > newsrv->maxconn) {
6537 /* Only 'minconn' was specified, or it was higher than or equal
6538 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6539 * this will avoid further useless expensive computations.
6540 */
6541 newsrv->maxconn = newsrv->minconn;
6542 } else if (newsrv->maxconn && !newsrv->minconn) {
6543 /* minconn was not specified, so we set it to maxconn */
6544 newsrv->minconn = newsrv->maxconn;
6545 }
6546
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006547#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006548 if (newsrv->use_ssl || newsrv->check.use_ssl)
6549 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006550#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006551
Willy Tarreau62c3be22012-01-20 13:12:32 +01006552 if (newsrv->trackit) {
6553 struct proxy *px;
6554 struct server *srv;
6555 char *pname, *sname;
6556
6557 pname = newsrv->trackit;
6558 sname = strrchr(pname, '/');
6559
6560 if (sname)
6561 *sname++ = '\0';
6562 else {
6563 sname = pname;
6564 pname = NULL;
6565 }
6566
6567 if (pname) {
6568 px = findproxy(pname, PR_CAP_BE);
6569 if (!px) {
6570 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6571 proxy_type_str(curproxy), curproxy->id,
6572 newsrv->id, pname);
6573 cfgerr++;
6574 goto next_srv;
6575 }
6576 } else
6577 px = curproxy;
6578
6579 srv = findserver(px, sname);
6580 if (!srv) {
6581 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6582 proxy_type_str(curproxy), curproxy->id,
6583 newsrv->id, sname);
6584 cfgerr++;
6585 goto next_srv;
6586 }
6587
6588 if (!(srv->state & SRV_CHECKED)) {
6589 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6590 "tracking as it does not have checks enabled.\n",
6591 proxy_type_str(curproxy), curproxy->id,
6592 newsrv->id, px->id, srv->id);
6593 cfgerr++;
6594 goto next_srv;
6595 }
6596
6597 if (curproxy != px &&
6598 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6599 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6600 "tracking: disable-on-404 option inconsistency.\n",
6601 proxy_type_str(curproxy), curproxy->id,
6602 newsrv->id, px->id, srv->id);
6603 cfgerr++;
6604 goto next_srv;
6605 }
6606
6607 /* if the other server is forced disabled, we have to do the same here */
6608 if (srv->state & SRV_MAINTAIN) {
6609 newsrv->state |= SRV_MAINTAIN;
6610 newsrv->state &= ~SRV_RUNNING;
6611 newsrv->health = 0;
6612 }
6613
6614 newsrv->track = srv;
6615 newsrv->tracknext = srv->tracknext;
6616 srv->tracknext = newsrv;
6617
6618 free(newsrv->trackit);
6619 newsrv->trackit = NULL;
6620 }
6621 next_srv:
6622 newsrv = newsrv->next;
6623 }
6624
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006625 /* We have to initialize the server lookup mechanism depending
6626 * on what LB algorithm was choosen.
6627 */
6628
6629 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6630 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6631 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006632 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6633 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6634 init_server_map(curproxy);
6635 } else {
6636 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6637 fwrr_init_server_groups(curproxy);
6638 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006639 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006640
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006641 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006642 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6643 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6644 fwlc_init_server_tree(curproxy);
6645 } else {
6646 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6647 fas_init_server_tree(curproxy);
6648 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006649 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006650
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006651 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006652 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6653 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6654 chash_init_server_tree(curproxy);
6655 } else {
6656 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6657 init_server_map(curproxy);
6658 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006659 break;
6660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006661
6662 if (curproxy->options & PR_O_LOGASAP)
6663 curproxy->to_log &= ~LW_BYTES;
6664
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006665 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006666 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006667 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6668 proxy_type_str(curproxy), curproxy->id);
6669 err_code |= ERR_WARN;
6670 }
6671
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006672 if (curproxy->mode != PR_MODE_HTTP) {
6673 int optnum;
6674
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006675 if (curproxy->uri_auth) {
6676 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6677 proxy_type_str(curproxy), curproxy->id);
6678 err_code |= ERR_WARN;
6679 curproxy->uri_auth = NULL;
6680 }
6681
Willy Tarreau87cf5142011-08-19 22:57:24 +02006682 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006683 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6684 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6685 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006686 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006687 }
6688
6689 if (curproxy->options & PR_O_ORGTO) {
6690 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6691 "originalto", proxy_type_str(curproxy), curproxy->id);
6692 err_code |= ERR_WARN;
6693 curproxy->options &= ~PR_O_ORGTO;
6694 }
6695
6696 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6697 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6698 (curproxy->cap & cfg_opts[optnum].cap) &&
6699 (curproxy->options & cfg_opts[optnum].val)) {
6700 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6701 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6702 err_code |= ERR_WARN;
6703 curproxy->options &= ~cfg_opts[optnum].val;
6704 }
6705 }
6706
6707 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6708 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6709 (curproxy->cap & cfg_opts2[optnum].cap) &&
6710 (curproxy->options2 & cfg_opts2[optnum].val)) {
6711 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6712 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6713 err_code |= ERR_WARN;
6714 curproxy->options2 &= ~cfg_opts2[optnum].val;
6715 }
6716 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006717
Willy Tarreauefa5f512010-03-30 20:13:29 +02006718#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006719 if (curproxy->conn_src.bind_hdr_occ) {
6720 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006721 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006722 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006723 err_code |= ERR_WARN;
6724 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006725#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006726 }
6727
Willy Tarreaubaaee002006-06-26 02:48:02 +02006728 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006729 * ensure that we're not cross-dressing a TCP server into HTTP.
6730 */
6731 newsrv = curproxy->srv;
6732 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006733 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006734 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6735 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006736 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006737 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006738
Willy Tarreau0cec3312011-10-31 13:49:26 +01006739 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6740 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6741 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6742 err_code |= ERR_WARN;
6743 }
6744
Willy Tarreauefa5f512010-03-30 20:13:29 +02006745#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006746 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6747 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006748 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 +01006749 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006750 err_code |= ERR_WARN;
6751 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006752#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006753 newsrv = newsrv->next;
6754 }
6755
Willy Tarreauc1a21672009-08-16 22:37:44 +02006756 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006757 if (!curproxy->accept)
6758 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006759
Willy Tarreauc1a21672009-08-16 22:37:44 +02006760 if (curproxy->tcp_req.inspect_delay ||
6761 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006762 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006763
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006764 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006765 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006766 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006767 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006768
6769 /* both TCP and HTTP must check switching rules */
6770 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6771 }
6772
6773 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006774 if (curproxy->tcp_req.inspect_delay ||
6775 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6776 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6777
Emeric Brun97679e72010-09-23 17:56:44 +02006778 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6779 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6780
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006781 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006782 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006783 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006784 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006785
6786 /* If the backend does requires RDP cookie persistence, we have to
6787 * enable the corresponding analyser.
6788 */
6789 if (curproxy->options2 & PR_O2_RDPC_PRST)
6790 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6791 }
6792
Emeric Brunc52962f2012-11-15 18:28:02 +01006793#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006794 /* Configure SSL for each bind line.
6795 * Note: if configuration fails at some point, the ->ctx member
6796 * remains NULL so that listeners can later detach.
6797 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006798 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006799 if (!bind_conf->is_ssl) {
6800 if (bind_conf->default_ctx) {
6801 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6802 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6803 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006804 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006805 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006806 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006807 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006808 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006809 cfgerr++;
6810 continue;
6811 }
6812
Emeric Brun4b3091e2012-09-24 15:48:52 +02006813 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006814 Alert("Unable to allocate SSL session cache.\n");
6815 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006816 continue;
6817 }
6818
Emeric Brunfc0421f2012-09-07 17:30:07 +02006819 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006820 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006821 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006822#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006823
Willy Tarreaue6b98942007-10-29 01:09:36 +01006824 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006825 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006826 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006827 if (!listener->luid) {
6828 /* listener ID not set, use automatic numbering with first
6829 * spare entry starting with next_luid.
6830 */
6831 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6832 listener->conf.id.key = listener->luid = next_id;
6833 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006834 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006835 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006836
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006837 /* enable separate counters */
6838 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6839 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006840 if (!listener->name)
6841 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006842 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006843
Willy Tarreaue6b98942007-10-29 01:09:36 +01006844 if (curproxy->options & PR_O_TCP_NOLING)
6845 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006846 if (!listener->maxconn)
6847 listener->maxconn = curproxy->maxconn;
6848 if (!listener->backlog)
6849 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006850 if (!listener->maxaccept)
6851 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6852
6853 /* we want to have an optimal behaviour on single process mode to
6854 * maximize the work at once, but in multi-process we want to keep
6855 * some fairness between processes, so we target half of the max
6856 * number of events to be balanced over all the processes the proxy
6857 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6858 * used to disable the limit.
6859 */
6860 if (listener->maxaccept > 0) {
6861 if (nbproc > 1)
6862 listener->maxaccept = (listener->maxaccept + 1) / 2;
6863 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6864 }
6865
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006866 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006867 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006868 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006869 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006870
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006871 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6872 listener->options |= LI_O_TCP_RULES;
6873
Willy Tarreaude3041d2010-05-31 10:56:17 +02006874 if (curproxy->mon_mask.s_addr)
6875 listener->options |= LI_O_CHK_MONNET;
6876
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006877 /* smart accept mode is automatic in HTTP mode */
6878 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006879 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006880 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6881 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006882 }
6883
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006884 /* Release unused SSL configs */
6885 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6886 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006887 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006888#ifdef USE_OPENSSL
6889 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006890 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006891 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006892 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006893 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006894#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006895 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006896
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006897 /* Check multi-process mode compatibility for the current proxy */
6898 if (global.nbproc > 1) {
6899 int nbproc = 0;
6900 if (curproxy->bind_proc) {
6901 int proc;
6902 for (proc = 0; proc < global.nbproc; proc++) {
6903 if (curproxy->bind_proc & (1 << proc)) {
6904 nbproc++;
6905 }
6906 }
6907 } else {
6908 nbproc = global.nbproc;
6909 }
6910 if (curproxy->table.peers.name) {
6911 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6912 curproxy->id);
6913 cfgerr++;
6914 }
6915 if (nbproc > 1) {
6916 if (curproxy->uri_auth) {
6917 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6918 curproxy->id);
6919 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6920 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6921 curproxy->id);
6922 }
6923 }
6924 if (curproxy->appsession_name) {
6925 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6926 curproxy->id);
6927 }
6928 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6929 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6930 curproxy->id);
6931 }
6932 }
6933 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006934
6935 /* create the task associated with the proxy */
6936 curproxy->task = task_new();
6937 if (curproxy->task) {
6938 curproxy->task->context = curproxy;
6939 curproxy->task->process = manage_proxy;
6940 /* no need to queue, it will be done automatically if some
6941 * listener gets limited.
6942 */
6943 curproxy->task->expire = TICK_ETERNITY;
6944 } else {
6945 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6946 curproxy->id);
6947 cfgerr++;
6948 }
6949
Willy Tarreaubaaee002006-06-26 02:48:02 +02006950 curproxy = curproxy->next;
6951 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006952
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006953 /* Check multi-process mode compatibility */
6954 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006955 if (global.stats_fe && !global.stats_fe->bind_proc) {
6956 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 +01006957 }
6958 }
6959
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006960 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6961 struct auth_users *curuser;
6962 int g;
6963
6964 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6965 unsigned int group_mask = 0;
6966 char *group = NULL;
6967
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006968 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006969 continue;
6970
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006971 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006972
6973 for (g = 0; g < curuserlist->grpcnt; g++)
6974 if (!strcmp(curuserlist->groups[g], group))
6975 break;
6976
6977 if (g == curuserlist->grpcnt) {
6978 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6979 curuserlist->name, group, curuser->user);
6980 err_code |= ERR_ALERT | ERR_FATAL;
6981 goto out;
6982 }
6983
6984 group_mask |= (1 << g);
6985 }
6986
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006987 free(curuser->u.groups);
6988 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006989 }
6990
6991 for (g = 0; g < curuserlist->grpcnt; g++) {
6992 char *user = NULL;
6993
6994 if (!curuserlist->groupusers[g])
6995 continue;
6996
6997 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6998 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6999 if (!strcmp(curuser->user, user))
7000 break;
7001
7002 if (!curuser) {
7003 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7004 curuserlist->name, user, curuserlist->groups[g]);
7005 err_code |= ERR_ALERT | ERR_FATAL;
7006 goto out;
7007 }
7008
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007009 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007010 }
7011
7012 free(curuserlist->groupusers[g]);
7013 }
7014
7015 free(curuserlist->groupusers);
7016
7017#ifdef DEBUG_AUTH
7018 for (g = 0; g < curuserlist->grpcnt; g++) {
7019 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7020
7021 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007022 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007023 fprintf(stderr, " %s", curuser->user);
7024 }
7025
7026 fprintf(stderr, "\n");
7027 }
7028#endif
7029
Willy Tarreaufbb78422011-06-05 15:38:35 +02007030 }
7031
7032 /* automatically compute fullconn if not set. We must not do it in the
7033 * loop above because cross-references are not yet fully resolved.
7034 */
7035 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7036 /* If <fullconn> is not set, let's set it to 10% of the sum of
7037 * the possible incoming frontend's maxconns.
7038 */
7039 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7040 struct proxy *fe;
7041 int total = 0;
7042
7043 /* sum up the number of maxconns of frontends which
7044 * reference this backend at least once or which are
7045 * the same one ('listen').
7046 */
7047 for (fe = proxy; fe; fe = fe->next) {
7048 struct switching_rule *rule;
7049 struct hdr_exp *exp;
7050 int found = 0;
7051
7052 if (!(fe->cap & PR_CAP_FE))
7053 continue;
7054
7055 if (fe == curproxy) /* we're on a "listen" instance */
7056 found = 1;
7057
7058 if (fe->defbe.be == curproxy) /* "default_backend" */
7059 found = 1;
7060
7061 /* check if a "use_backend" rule matches */
7062 if (!found) {
7063 list_for_each_entry(rule, &fe->switching_rules, list) {
7064 if (rule->be.backend == curproxy) {
7065 found = 1;
7066 break;
7067 }
7068 }
7069 }
7070
7071 /* check if a "reqsetbe" rule matches */
7072 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7073 if (exp->action == ACT_SETBE &&
7074 (struct proxy *)exp->replace == curproxy) {
7075 found = 1;
7076 break;
7077 }
7078 }
7079
7080 /* now we've checked all possible ways to reference a backend
7081 * from a frontend.
7082 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007083 if (!found)
7084 continue;
7085 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007086 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007087 /* we have the sum of the maxconns in <total>. We only
7088 * keep 10% of that sum to set the default fullconn, with
7089 * a hard minimum of 1 (to avoid a divide by zero).
7090 */
7091 curproxy->fullconn = (total + 9) / 10;
7092 if (!curproxy->fullconn)
7093 curproxy->fullconn = 1;
7094 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007095 }
7096
Willy Tarreau056f5682010-06-06 15:51:11 +02007097 /* initialize stick-tables on backend capable proxies. This must not
7098 * be done earlier because the data size may be discovered while parsing
7099 * other proxies.
7100 */
7101 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007102 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007103
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007104 /*
7105 * Recount currently required checks.
7106 */
7107
7108 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7109 int optnum;
7110
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007111 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7112 if (curproxy->options & cfg_opts[optnum].val)
7113 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007114
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007115 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7116 if (curproxy->options2 & cfg_opts2[optnum].val)
7117 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007118 }
7119
Willy Tarreau122541c2011-09-07 21:24:49 +02007120 if (peers) {
7121 struct peers *curpeers = peers, **last;
7122 struct peer *p, *pb;
7123
7124 /* Remove all peers sections which don't have a valid listener.
7125 * This can happen when a peers section is never referenced and
7126 * does not contain a local peer.
7127 */
7128 last = &peers;
7129 while (*last) {
7130 curpeers = *last;
7131 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007132 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007133 last = &curpeers->next;
7134 continue;
7135 }
7136
7137 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7138 curpeers->id, localpeer);
7139
7140 p = curpeers->remote;
7141 while (p) {
7142 pb = p->next;
7143 free(p->id);
7144 free(p);
7145 p = pb;
7146 }
7147
7148 /* Destroy and unlink this curpeers section.
7149 * Note: curpeers is backed up into *last.
7150 */
7151 free(curpeers->id);
7152 curpeers = curpeers->next;
7153 free(*last);
7154 *last = curpeers;
7155 }
7156 }
7157
Willy Tarreau34eb6712011-10-24 18:15:04 +02007158 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007159 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007160 MEM_F_SHARED);
7161
Willy Tarreaubb925012009-07-23 13:36:36 +02007162 if (cfgerr > 0)
7163 err_code |= ERR_ALERT | ERR_FATAL;
7164 out:
7165 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007166}
7167
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007168/*
7169 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7170 * parsing sessions.
7171 */
7172void cfg_register_keywords(struct cfg_kw_list *kwl)
7173{
7174 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7175}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007176
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007177/*
7178 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7179 */
7180void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7181{
7182 LIST_DEL(&kwl->list);
7183 LIST_INIT(&kwl->list);
7184}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007185
7186/*
7187 * Local variables:
7188 * c-indent-level: 8
7189 * c-basic-offset: 8
7190 * End:
7191 */