blob: d3b630051fb822e887fd4daacc6cd542c08818e7 [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
566 else if (!strcmp(args[0], "tune.sslcachesize")) {
567 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 }
574#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200575 else if (!strcmp(args[0], "tune.bufsize")) {
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.tune.bufsize = atol(args[1]);
582 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
583 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100584 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200585 }
586 else if (!strcmp(args[0], "tune.maxrewrite")) {
587 if (*(args[1]) == 0) {
588 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
589 err_code |= ERR_ALERT | ERR_FATAL;
590 goto out;
591 }
592 global.tune.maxrewrite = atol(args[1]);
593 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
594 global.tune.maxrewrite = global.tune.bufsize / 2;
595 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100596 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
597 if (global.tune.client_rcvbuf != 0) {
598 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
599 err_code |= ERR_ALERT;
600 goto out;
601 }
602 if (*(args[1]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
606 }
607 global.tune.client_rcvbuf = atol(args[1]);
608 }
609 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
610 if (global.tune.server_rcvbuf != 0) {
611 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT;
613 goto out;
614 }
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620 global.tune.server_rcvbuf = atol(args[1]);
621 }
622 else if (!strcmp(args[0], "tune.sndbuf.client")) {
623 if (global.tune.client_sndbuf != 0) {
624 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT;
626 goto out;
627 }
628 if (*(args[1]) == 0) {
629 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
630 err_code |= ERR_ALERT | ERR_FATAL;
631 goto out;
632 }
633 global.tune.client_sndbuf = atol(args[1]);
634 }
635 else if (!strcmp(args[0], "tune.sndbuf.server")) {
636 if (global.tune.server_sndbuf != 0) {
637 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT;
639 goto out;
640 }
641 if (*(args[1]) == 0) {
642 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646 global.tune.server_sndbuf = atol(args[1]);
647 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200648 else if (!strcmp(args[0], "tune.pipesize")) {
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.pipesize = atol(args[1]);
655 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200656 else if (!strcmp(args[0], "tune.http.maxhdr")) {
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.max_http_hdr = atol(args[1]);
663 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100664 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
665#ifdef USE_ZLIB
666 if (*args[1]) {
667 global.tune.zlibmemlevel = atoi(args[1]);
668 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
669 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
670 file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 } else {
675 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
676 file, linenum, args[0]);
677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
679 }
680#else
681 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
684#endif
685 }
686 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
687#ifdef USE_ZLIB
688 if (*args[1]) {
689 global.tune.zlibwindowsize = atoi(args[1]);
690 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
691 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
692 file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 } else {
697 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\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' is not implemented.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706#endif
707 }
William Lallemandf3747832012-11-09 12:33:10 +0100708 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
709 if (*args[1]) {
710 global.tune.comp_maxlevel = atoi(args[1]);
711 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
712 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
713 file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 } else {
718 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
719 file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 else if (!strcmp(args[0], "uid")) {
725 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200726 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 err_code |= ERR_ALERT;
728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 global.uid = atol(args[1]);
736 }
737 else if (!strcmp(args[0], "gid")) {
738 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200739 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 global.gid = atol(args[1]);
749 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200750 /* user/group name handling */
751 else if (!strcmp(args[0], "user")) {
752 struct passwd *ha_user;
753 if (global.uid != 0) {
754 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 Tarreau95c20ac2007-03-25 15:39:23 +0200757 }
758 errno = 0;
759 ha_user = getpwnam(args[1]);
760 if (ha_user != NULL) {
761 global.uid = (int)ha_user->pw_uid;
762 }
763 else {
764 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 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200766 }
767 }
768 else if (!strcmp(args[0], "group")) {
769 struct group *ha_group;
770 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200771 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200772 err_code |= ERR_ALERT;
773 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 }
775 errno = 0;
776 ha_group = getgrnam(args[1]);
777 if (ha_group != NULL) {
778 global.gid = (int)ha_group->gr_gid;
779 }
780 else {
781 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 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200783 }
784 }
785 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 else if (!strcmp(args[0], "nbproc")) {
787 if (global.nbproc != 0) {
788 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200789 err_code |= ERR_ALERT;
790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791 }
792 if (*(args[1]) == 0) {
793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200796 }
797 global.nbproc = atol(args[1]);
798 }
799 else if (!strcmp(args[0], "maxconn")) {
800 if (global.maxconn != 0) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 global.maxconn = atol(args[1]);
811#ifdef SYSTEM_MAXCONN
812 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
813 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);
814 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200816 }
817#endif /* SYSTEM_MAXCONN */
818 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200819 else if (!strcmp(args[0], "maxsslconn")) {
820#ifdef USE_OPENSSL
821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.maxsslconn = atol(args[1]);
827#else
Emeric Brun0914df82012-10-02 18:45:42 +0200828 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200831#endif
832 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200833 else if (!strcmp(args[0], "maxconnrate")) {
834 if (global.cps_lim != 0) {
835 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT;
837 goto out;
838 }
839 if (*(args[1]) == 0) {
840 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
841 err_code |= ERR_ALERT | ERR_FATAL;
842 goto out;
843 }
844 global.cps_lim = atol(args[1]);
845 }
William Lallemandd85f9172012-11-09 17:05:39 +0100846 else if (!strcmp(args[0], "maxcomprate")) {
847 if (*(args[1]) == 0) {
848 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852 global.comp_rate_lim = atoi(args[1]) * 1024;
853 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100854 else if (!strcmp(args[0], "maxpipes")) {
855 if (global.maxpipes != 0) {
856 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200857 err_code |= ERR_ALERT;
858 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100859 }
860 if (*(args[1]) == 0) {
861 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100864 }
865 global.maxpipes = atol(args[1]);
866 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100867 else if (!strcmp(args[0], "maxzlibmem")) {
868 if (*(args[1]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.maxzlibmem = atol(args[1]);
874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 else if (!strcmp(args[0], "ulimit-n")) {
876 if (global.rlimit_nofile != 0) {
877 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 err_code |= ERR_ALERT;
879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 }
881 if (*(args[1]) == 0) {
882 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
886 global.rlimit_nofile = atol(args[1]);
887 }
888 else if (!strcmp(args[0], "chroot")) {
889 if (global.chroot != NULL) {
890 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200891 err_code |= ERR_ALERT;
892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893 }
894 if (*(args[1]) == 0) {
895 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 }
899 global.chroot = strdup(args[1]);
900 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200901 else if (!strcmp(args[0], "description")) {
902 int i, len=0;
903 char *d;
904
905 if (!*args[1]) {
906 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
907 file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911
912 for(i=1; *args[i]; i++)
913 len += strlen(args[i])+1;
914
915 if (global.desc)
916 free(global.desc);
917
918 global.desc = d = (char *)calloc(1, len);
919
920 d += sprintf(d, "%s", args[1]);
921 for(i=2; *args[i]; i++)
922 d += sprintf(d, " %s", args[i]);
923 }
924 else if (!strcmp(args[0], "node")) {
925 int i;
926 char c;
927
928 for (i=0; args[1][i]; i++) {
929 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100930 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
931 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200932 break;
933 }
934
935 if (!i || args[1][i]) {
936 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
937 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
938 file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942
943 if (global.node)
944 free(global.node);
945
946 global.node = strdup(args[1]);
947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 else if (!strcmp(args[0], "pidfile")) {
949 if (global.pidfile != NULL) {
950 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200951 err_code |= ERR_ALERT;
952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 }
954 if (*(args[1]) == 0) {
955 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 }
959 global.pidfile = strdup(args[1]);
960 }
Emeric Bruned760922010-10-22 17:59:25 +0200961 else if (!strcmp(args[0], "unix-bind")) {
962 int cur_arg = 1;
963 while (*(args[cur_arg])) {
964 if (!strcmp(args[cur_arg], "prefix")) {
965 if (global.unix_bind.prefix != NULL) {
966 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
967 err_code |= ERR_ALERT;
968 cur_arg += 2;
969 continue;
970 }
971
972 if (*(args[cur_arg+1]) == 0) {
973 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.unix_bind.prefix = strdup(args[cur_arg+1]);
978 cur_arg += 2;
979 continue;
980 }
981
982 if (!strcmp(args[cur_arg], "mode")) {
983
984 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
985 cur_arg += 2;
986 continue;
987 }
988
989 if (!strcmp(args[cur_arg], "uid")) {
990
991 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
992 cur_arg += 2;
993 continue;
994 }
995
996 if (!strcmp(args[cur_arg], "gid")) {
997
998 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
999 cur_arg += 2;
1000 continue;
1001 }
1002
1003 if (!strcmp(args[cur_arg], "user")) {
1004 struct passwd *user;
1005
1006 user = getpwnam(args[cur_arg + 1]);
1007 if (!user) {
1008 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1009 file, linenum, args[0], args[cur_arg + 1 ]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013
1014 global.unix_bind.ux.uid = user->pw_uid;
1015 cur_arg += 2;
1016 continue;
1017 }
1018
1019 if (!strcmp(args[cur_arg], "group")) {
1020 struct group *group;
1021
1022 group = getgrnam(args[cur_arg + 1]);
1023 if (!group) {
1024 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1025 file, linenum, args[0], args[cur_arg + 1 ]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029
1030 global.unix_bind.ux.gid = group->gr_gid;
1031 cur_arg += 2;
1032 continue;
1033 }
1034
Willy Tarreaub48f9582011-09-05 01:17:06 +02001035 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001036 file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 }
William Lallemand0f99e342011-10-12 17:50:54 +02001041 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1042 /* delete previous herited or defined syslog servers */
1043 struct logsrv *back;
1044 struct logsrv *tmp;
1045
1046 if (*(args[1]) != 0) {
1047 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050 }
1051
1052 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1053 LIST_DEL(&tmp->list);
1054 free(tmp);
1055 }
1056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001058 struct logsrv *logsrv;
1059
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 if (*(args[1]) == 0 || *(args[2]) == 0) {
1061 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 }
William Lallemand0f99e342011-10-12 17:50:54 +02001065
1066 logsrv = calloc(1, sizeof(struct logsrv));
1067
1068 logsrv->facility = get_log_facility(args[2]);
1069 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001072 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074
William Lallemand0f99e342011-10-12 17:50:54 +02001075 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001077 logsrv->level = get_log_level(args[3]);
1078 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001081 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
1083 }
1084
William Lallemand0f99e342011-10-12 17:50:54 +02001085 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001086 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001087 logsrv->minlvl = get_log_level(args[4]);
1088 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001089 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001091 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001092 }
1093 }
1094
Robert Tsai81ae1952007-12-05 10:47:29 +01001095 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001096 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001097 if (!sk) {
1098 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001099 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001100 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001101 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001102 goto out;
1103 }
William Lallemand0f99e342011-10-12 17:50:54 +02001104 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001105 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001106 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001107 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001108 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001110 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001111 goto out;
1112 }
William Lallemand0f99e342011-10-12 17:50:54 +02001113 logsrv->addr = *sk;
1114 if (!get_host_port(&logsrv->addr))
1115 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117
William Lallemand0f99e342011-10-12 17:50:54 +02001118 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001119 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001120 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1121 char *name;
1122 int len;
1123
1124 if (global.log_send_hostname != NULL) {
1125 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1126 err_code |= ERR_ALERT;
1127 goto out;
1128 }
1129
1130 if (*(args[1]))
1131 name = args[1];
1132 else
1133 name = hostname;
1134
1135 len = strlen(name);
1136
1137 /* We'll add a space after the name to respect the log format */
1138 free(global.log_send_hostname);
1139 global.log_send_hostname = malloc(len + 2);
1140 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1141 }
Kevinm48936af2010-12-22 16:08:21 +00001142 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148 free(global.log_tag);
1149 global.log_tag = strdup(args[1]);
1150 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001151 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1152 if (global.spread_checks != 0) {
1153 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT;
1155 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001156 }
1157 if (*(args[1]) == 0) {
1158 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001161 }
1162 global.spread_checks = atol(args[1]);
1163 if (global.spread_checks < 0 || global.spread_checks > 50) {
1164 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001165 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 }
1168 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001169 struct cfg_kw_list *kwl;
1170 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001171 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001172
1173 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1174 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1175 if (kwl->kw[index].section != CFG_GLOBAL)
1176 continue;
1177 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001178 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001179 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001180 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001181 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001182 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001183 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001184 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_WARN;
1186 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001187 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001188 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001189 }
1190 }
1191 }
1192
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001194 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001196
Willy Tarreau058e9072009-07-20 09:30:05 +02001197 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001198 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001199 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200}
1201
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001202void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001204 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 defproxy.mode = PR_MODE_TCP;
1206 defproxy.state = PR_STNEW;
1207 defproxy.maxconn = cfg_maxpconn;
1208 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001209
1210 defproxy.defsrv.inter = DEF_CHKINTR;
1211 defproxy.defsrv.fastinter = 0;
1212 defproxy.defsrv.downinter = 0;
1213 defproxy.defsrv.rise = DEF_RISETIME;
1214 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001215 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001216 defproxy.defsrv.maxqueue = 0;
1217 defproxy.defsrv.minconn = 0;
1218 defproxy.defsrv.maxconn = 0;
1219 defproxy.defsrv.slowstart = 0;
1220 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1221 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1222 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223}
1224
Willy Tarreauade5ec42010-01-28 19:33:49 +01001225
1226static int create_cond_regex_rule(const char *file, int line,
1227 struct proxy *px, int dir, int action, int flags,
1228 const char *cmd, const char *reg, const char *repl,
1229 const char **cond_start)
1230{
1231 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001232 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001233 const char *err;
1234 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001235 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001236
1237 if (px == &defproxy) {
1238 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto err;
1241 }
1242
1243 if (*reg == 0) {
1244 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto err;
1247 }
1248
1249 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1250 err_code |= ERR_WARN;
1251
Willy Tarreau5321c422010-01-28 20:35:13 +01001252 if (cond_start &&
1253 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001254 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1255 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1256 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto err;
1259 }
1260 }
1261 else if (cond_start && **cond_start) {
1262 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1263 file, line, cmd, *cond_start);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto err;
1266 }
1267
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001268 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001269 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001270 else
1271 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001272
Willy Tarreauade5ec42010-01-28 19:33:49 +01001273 preg = calloc(1, sizeof(regex_t));
1274 if (!preg) {
1275 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1276 err_code = ERR_ALERT | ERR_FATAL;
1277 goto err;
1278 }
1279
1280 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1281 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1282 err_code = ERR_ALERT | ERR_FATAL;
1283 goto err;
1284 }
1285
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001286 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001287 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001288 if (repl && err) {
1289 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1290 file, line, cmd, *err);
1291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto err;
1293 }
1294
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001295 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001296 err_code |= ERR_WARN;
1297
Willy Tarreauf4068b62012-05-08 17:37:49 +02001298 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001299 return err_code;
1300 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001301 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001302 free(preg);
1303 return err_code;
1304}
1305
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001307 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001308 * Returns the error code, 0 if OK, or any combination of :
1309 * - ERR_ABORT: must abort ASAP
1310 * - ERR_FATAL: we can continue parsing but not start the service
1311 * - ERR_WARN: a warning has been emitted
1312 * - ERR_ALERT: an alert has been emitted
1313 * Only the two first ones can stop processing, the two others are just
1314 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001316int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1317{
1318 static struct peers *curpeers = NULL;
1319 struct peer *newpeer = NULL;
1320 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001321 struct bind_conf *bind_conf;
1322 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001323 int err_code = 0;
1324
1325 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1326
1327 err = invalid_char(args[1]);
1328 if (err) {
1329 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1330 file, linenum, *err, args[0], args[1]);
1331 err_code |= ERR_ALERT | ERR_FATAL;
1332 }
1333
1334 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1335 /*
1336 * If there are two proxies with the same name only following
1337 * combinations are allowed:
1338 */
1339 if (strcmp(curpeers->id, args[1]) == 0) {
1340 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1341 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1342 err_code |= ERR_WARN;
1343 }
1344 }
1345
1346 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1348 err_code |= ERR_ALERT | ERR_ABORT;
1349 goto out;
1350 }
1351
1352 curpeers->next = peers;
1353 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001354 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001355 curpeers->conf.line = linenum;
1356 curpeers->last_change = now.tv_sec;
1357 curpeers->id = strdup(args[1]);
1358 }
1359 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1360 char *rport, *raddr;
1361 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001362 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001363 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001364
1365 if (!*args[2]) {
1366 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1367 file, linenum, args[0]);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
1370 }
1371
1372 err = invalid_char(args[1]);
1373 if (err) {
1374 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1375 file, linenum, *err, args[1]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379
1380 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1382 err_code |= ERR_ALERT | ERR_ABORT;
1383 goto out;
1384 }
1385
1386 /* the peers are linked backwards first */
1387 curpeers->count++;
1388 newpeer->next = curpeers->remote;
1389 curpeers->remote = newpeer;
1390 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001391 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001392 newpeer->conf.line = linenum;
1393
1394 newpeer->last_change = now.tv_sec;
1395 newpeer->id = strdup(args[1]);
1396
1397 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001398 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001399 if (rport) {
1400 *rport++ = 0;
1401 realport = atol(rport);
1402 }
1403 if (!realport) {
1404 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
1406 goto out;
1407 }
1408
Willy Tarreaufab5a432011-03-04 15:31:53 +01001409 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001410 free(raddr);
1411 if (!sk) {
1412 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto out;
1415 }
1416 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001417 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001418 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001419 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001420
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001421 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001422 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1423 file, linenum, newpeer->addr.ss_family, args[2]);
1424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
1426 }
1427
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001428 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001429
1430 if (strcmp(newpeer->id, localpeer) == 0) {
1431 /* Current is local peer, it define a frontend */
1432 newpeer->local = 1;
1433
1434 if (!curpeers->peers_fe) {
1435 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1436 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1437 err_code |= ERR_ALERT | ERR_ABORT;
1438 goto out;
1439 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001440
Willy Tarreau237250c2011-07-29 01:49:03 +02001441 init_new_proxy(curpeers->peers_fe);
1442 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001443
1444 curpeers->peers_fe->last_change = now.tv_sec;
1445 curpeers->peers_fe->id = strdup(args[1]);
1446 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001447 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001448 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1449 curpeers->peers_fe->timeout.connect = 5000;
1450 curpeers->peers_fe->accept = peer_accept;
1451 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001452
1453 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1454
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001455 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1456 if (err_msg && *err_msg) {
1457 indent_msg(&err_msg, 2);
1458 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1459 }
1460 else
1461 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1462 file, linenum, args[0], args[1], args[2]);
1463 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001464 err_code |= ERR_FATAL;
1465 goto out;
1466 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001467
1468 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1469 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1470 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1471 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1472 l->accept = session_accept;
1473 l->handler = process_session;
1474 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1475 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1476 global.maxsock += l->maxconn;
1477 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 }
1479 }
1480 } /* neither "peer" nor "peers" */
1481 else if (*args[0] != 0) {
1482 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
1485 }
1486
1487out:
1488 return err_code;
1489}
1490
1491
Willy Tarreau3842f002009-06-14 11:39:52 +02001492int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493{
1494 static struct proxy *curproxy = NULL;
1495 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001496 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001497 int rc;
1498 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001499 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001500 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001501 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001502 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001503 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 if (!strcmp(args[0], "listen"))
1506 rc = PR_CAP_LISTEN;
1507 else if (!strcmp(args[0], "frontend"))
1508 rc = PR_CAP_FE | PR_CAP_RS;
1509 else if (!strcmp(args[0], "backend"))
1510 rc = PR_CAP_BE | PR_CAP_RS;
1511 else if (!strcmp(args[0], "ruleset"))
1512 rc = PR_CAP_RS;
1513 else
1514 rc = PR_CAP_NONE;
1515
1516 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 if (!*args[1]) {
1518 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1519 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001521 err_code |= ERR_ALERT | ERR_ABORT;
1522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001524
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001525 err = invalid_char(args[1]);
1526 if (err) {
1527 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1528 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001529 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001530 }
1531
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001532 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1533 /*
1534 * If there are two proxies with the same name only following
1535 * combinations are allowed:
1536 *
1537 * listen backend frontend ruleset
1538 * listen - - - -
1539 * backend - - OK -
1540 * frontend - OK - -
1541 * ruleset - - - -
1542 */
1543
1544 if (!strcmp(curproxy->id, args[1]) &&
1545 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1546 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001547 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1548 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1549 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001550 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001551 }
1552 }
1553
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001556 err_code |= ERR_ALERT | ERR_ABORT;
1557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001559
Willy Tarreau97cb7802010-01-03 20:23:58 +01001560 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 curproxy->next = proxy;
1562 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001563 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001564 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001565 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568
1569 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001570 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001571 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001572 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001573
Willy Tarreau4348fad2012-09-20 16:48:07 +02001574 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1575
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001576 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1577 if (err_msg && *err_msg) {
1578 indent_msg(&err_msg, 2);
1579 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1580 }
1581 else
1582 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1583 file, linenum, args[0], args[1], args[2]);
1584 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_FATAL;
1586 goto out;
1587 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001588
Willy Tarreau4348fad2012-09-20 16:48:07 +02001589 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001590 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 }
1593
1594 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001595 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001596 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001597
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001600 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001601 curproxy->no_options = defproxy.no_options;
1602 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001603 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001604 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001605 curproxy->except_net = defproxy.except_net;
1606 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001607 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001608 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001610 if (defproxy.fwdfor_hdr_len) {
1611 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1612 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1613 }
1614
Willy Tarreaub86db342009-11-30 11:50:16 +01001615 if (defproxy.orgto_hdr_len) {
1616 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1617 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1618 }
1619
Mark Lamourinec2247f02012-01-04 13:02:01 -05001620 if (defproxy.server_id_hdr_len) {
1621 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1622 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1623 }
1624
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625 if (curproxy->cap & PR_CAP_FE) {
1626 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001627 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001628 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001629
1630 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001631 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1632 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001633
1634 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (curproxy->cap & PR_CAP_BE) {
1638 curproxy->fullconn = defproxy.fullconn;
1639 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001641 if (defproxy.check_req) {
1642 curproxy->check_req = calloc(1, defproxy.check_len);
1643 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001645 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001647 if (defproxy.expect_str) {
1648 curproxy->expect_str = strdup(defproxy.expect_str);
1649 if (defproxy.expect_regex) {
1650 /* note: this regex is known to be valid */
1651 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1652 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1653 }
1654 }
1655
Willy Tarreau67402132012-05-31 20:40:20 +02001656 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001657 if (defproxy.cookie_name)
1658 curproxy->cookie_name = strdup(defproxy.cookie_name);
1659 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001660 if (defproxy.cookie_domain)
1661 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001662
Willy Tarreau31936852010-10-06 16:59:56 +02001663 if (defproxy.cookie_maxidle)
1664 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1665
1666 if (defproxy.cookie_maxlife)
1667 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1668
Emeric Brun647caf12009-06-30 17:57:00 +02001669 if (defproxy.rdp_cookie_name)
1670 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1671 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1672
Willy Tarreau01732802007-11-01 22:48:15 +01001673 if (defproxy.url_param_name)
1674 curproxy->url_param_name = strdup(defproxy.url_param_name);
1675 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001676
Benoitaffb4812009-03-25 13:02:10 +01001677 if (defproxy.hh_name)
1678 curproxy->hh_name = strdup(defproxy.hh_name);
1679 curproxy->hh_len = defproxy.hh_len;
1680 curproxy->hh_match_domain = defproxy.hh_match_domain;
1681
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001682 if (defproxy.iface_name)
1683 curproxy->iface_name = strdup(defproxy.iface_name);
1684 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001687 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001688 if (defproxy.capture_name)
1689 curproxy->capture_name = strdup(defproxy.capture_name);
1690 curproxy->capture_namelen = defproxy.capture_namelen;
1691 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693
Willy Tarreau977b8e42006-12-29 14:19:17 +01001694 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001695 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001696 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001697 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001698 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->uri_auth = defproxy.uri_auth;
1700 curproxy->mon_net = defproxy.mon_net;
1701 curproxy->mon_mask = defproxy.mon_mask;
1702 if (defproxy.monitor_uri)
1703 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1704 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001705 if (defproxy.defbe.name)
1706 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001707
1708 /* get either a pointer to the logformat string or a copy of it */
1709 curproxy->logformat_string = defproxy.logformat_string;
1710 if (curproxy->logformat_string &&
1711 curproxy->logformat_string != default_http_log_format &&
1712 curproxy->logformat_string != default_tcp_log_format &&
1713 curproxy->logformat_string != clf_http_log_format)
1714 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001715 }
1716
1717 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001718 curproxy->timeout.connect = defproxy.timeout.connect;
1719 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001720 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001721 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001722 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001723 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001724 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001725 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001726 curproxy->source_addr = defproxy.source_addr;
1727 }
1728
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001730
1731 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001732 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001733 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001734 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001735 LIST_INIT(&node->list);
1736 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1737 }
1738
Willy Tarreau196729e2012-05-31 19:30:26 +02001739 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1740 if (curproxy->uniqueid_format_string)
1741 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001742
1743 /* copy default header unique id */
1744 if (defproxy.header_unique_id)
1745 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1746
William Lallemand82fe75c2012-10-23 10:25:10 +02001747 /* default compression options */
1748 if (defproxy.comp != NULL) {
1749 curproxy->comp = calloc(1, sizeof(struct comp));
1750 curproxy->comp->algos = defproxy.comp->algos;
1751 curproxy->comp->types = defproxy.comp->types;
1752 }
1753
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001755 curproxy->conf.used_listener_id = EB_ROOT;
1756 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001757
Willy Tarreau93893792009-07-23 13:19:11 +02001758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 }
1760 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1761 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001762 /* FIXME-20070101: we should do this too at the end of the
1763 * config parsing to free all default values.
1764 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001765 free(defproxy.check_req);
1766 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001767 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001768 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001769 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001770 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001771 free(defproxy.capture_name);
1772 free(defproxy.monitor_uri);
1773 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001774 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001775 free(defproxy.fwdfor_hdr_name);
1776 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001777 free(defproxy.orgto_hdr_name);
1778 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001779 free(defproxy.server_id_hdr_name);
1780 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001781 free(defproxy.expect_str);
1782 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001783
Willy Tarreau39b06652012-06-01 10:58:06 +02001784 if (defproxy.logformat_string != default_http_log_format &&
1785 defproxy.logformat_string != default_tcp_log_format &&
1786 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001787 free(defproxy.logformat_string);
1788
1789 free(defproxy.uniqueid_format_string);
1790
Willy Tarreaua534fea2008-08-03 12:19:50 +02001791 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001792 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001793
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 /* we cannot free uri_auth because it might already be used */
1795 init_default_instance();
1796 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001797 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799 }
1800 else if (curproxy == NULL) {
1801 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 }
1805
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806
1807 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001809 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001810 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001811 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001812
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 if (curproxy == &defproxy) {
1814 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001818 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001819 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820
Emeric Bruned760922010-10-22 17:59:25 +02001821 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001822 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001826 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001827
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001828 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001829 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001830
1831 /* NOTE: the following line might create several listeners if there
1832 * are comma-separated IPs or port ranges. So all further processing
1833 * will have to be applied to all listeners created after last_listen.
1834 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001835 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1836 if (err_msg && *err_msg) {
1837 indent_msg(&err_msg, 2);
1838 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1839 }
1840 else
1841 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1842 file, linenum, args[0], args[1]);
1843 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001847
Willy Tarreau4348fad2012-09-20 16:48:07 +02001848 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1849 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001850 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001851 }
1852
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001853 cur_arg = 2;
1854 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001855 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001856 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001857 char *err;
1858
Willy Tarreau26982662012-09-12 23:17:10 +02001859 kw = bind_find_kw(args[cur_arg]);
1860 if (kw) {
1861 char *err = NULL;
1862 int code;
1863
1864 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001865 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1866 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001867 cur_arg += 1 + kw->skip ;
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871
Willy Tarreau4348fad2012-09-20 16:48:07 +02001872 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001873 err_code |= code;
1874
1875 if (code) {
1876 if (err && *err) {
1877 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001878 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001879 }
1880 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001881 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1882 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001883 if (code & ERR_FATAL) {
1884 free(err);
1885 cur_arg += 1 + kw->skip;
1886 goto out;
1887 }
1888 }
1889 free(err);
1890 cur_arg += 1 + kw->skip;
1891 continue;
1892 }
1893
Willy Tarreau8638f482012-09-18 18:01:17 +02001894 err = NULL;
1895 if (!bind_dumped) {
1896 bind_dump_kws(&err);
1897 indent_msg(&err, 4);
1898 bind_dumped = 1;
1899 }
1900
1901 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1902 file, linenum, args[0], args[1], args[cur_arg],
1903 err ? " Registered keywords :" : "", err ? err : "");
1904 free(err);
1905
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001908 }
Willy Tarreau93893792009-07-23 13:19:11 +02001909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 }
1911 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1912 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1913 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 /* flush useless bits */
1922 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001925 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928
Willy Tarreau1c47f852006-07-09 08:22:27 +02001929 if (!*args[1]) {
1930 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1931 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001934 }
1935
Willy Tarreaua534fea2008-08-03 12:19:50 +02001936 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001937 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001938 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001939 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001940 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1941
Willy Tarreau93893792009-07-23 13:19:11 +02001942 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1945 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1946 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1947 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1948 else {
1949 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
1953 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001955 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956
1957 if (curproxy == &defproxy) {
1958 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1959 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001962 }
1963
1964 if (!*args[1]) {
1965 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001969 }
1970
1971 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001972 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001973
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001974 if (curproxy->uuid <= 0) {
1975 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001977 err_code |= ERR_ALERT | ERR_FATAL;
1978 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001979 }
1980
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001981 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1982 if (node) {
1983 struct proxy *target = container_of(node, struct proxy, conf.id);
1984 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1985 file, linenum, proxy_type_str(curproxy), curproxy->id,
1986 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
1989 }
1990 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001991 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001992 else if (!strcmp(args[0], "description")) {
1993 int i, len=0;
1994 char *d;
1995
Cyril Bonté99ed3272010-01-24 23:29:44 +01001996 if (curproxy == &defproxy) {
1997 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1998 file, linenum, args[0]);
1999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
2001 }
2002
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002003 if (!*args[1]) {
2004 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2005 file, linenum, args[0]);
2006 return -1;
2007 }
2008
2009 for(i=1; *args[i]; i++)
2010 len += strlen(args[i])+1;
2011
2012 d = (char *)calloc(1, len);
2013 curproxy->desc = d;
2014
2015 d += sprintf(d, "%s", args[1]);
2016 for(i=2; *args[i]; i++)
2017 d += sprintf(d, " %s", args[i]);
2018
2019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2021 curproxy->state = PR_STSTOPPED;
2022 }
2023 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2024 curproxy->state = PR_STNEW;
2025 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002026 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2027 int cur_arg = 1;
2028 unsigned int set = 0;
2029
2030 while (*args[cur_arg]) {
2031 int u;
2032 if (strcmp(args[cur_arg], "all") == 0) {
2033 set = 0;
2034 break;
2035 }
2036 else if (strcmp(args[cur_arg], "odd") == 0) {
2037 set |= 0x55555555;
2038 }
2039 else if (strcmp(args[cur_arg], "even") == 0) {
2040 set |= 0xAAAAAAAA;
2041 }
2042 else {
2043 u = str2uic(args[cur_arg]);
2044 if (u < 1 || u > 32) {
2045 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002049 }
2050 if (u > global.nbproc) {
2051 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002054 }
2055 set |= 1 << (u - 1);
2056 }
2057 cur_arg++;
2058 }
2059 curproxy->bind_proc = set;
2060 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002061 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002062 if (curproxy == &defproxy) {
2063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002066 }
2067
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002068 err = invalid_char(args[1]);
2069 if (err) {
2070 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2071 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002073 }
2074
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002075 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2076 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2077 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002080 }
2081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2083 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084
Willy Tarreau977b8e42006-12-29 14:19:17 +01002085 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (*(args[1]) == 0) {
2089 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2090 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002094
Willy Tarreau67402132012-05-31 20:40:20 +02002095 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002096 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002097 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002098 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 curproxy->cookie_name = strdup(args[1]);
2100 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002101
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 cur_arg = 2;
2103 while (*(args[cur_arg])) {
2104 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002105 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002108 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 }
2110 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002111 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
2113 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002114 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
2116 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002117 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002119 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002120 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002123 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002125 else if (!strcmp(args[cur_arg], "httponly")) {
2126 curproxy->ck_opts |= PR_CK_HTTPONLY;
2127 }
2128 else if (!strcmp(args[cur_arg], "secure")) {
2129 curproxy->ck_opts |= PR_CK_SECURE;
2130 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002131 else if (!strcmp(args[cur_arg], "domain")) {
2132 if (!*args[cur_arg + 1]) {
2133 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2134 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002137 }
2138
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002139 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002140 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002141 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2142 " dots nor does not start with a dot."
2143 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002144 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002145 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002146 }
2147
2148 err = invalid_domainchar(args[cur_arg + 1]);
2149 if (err) {
2150 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2151 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002154 }
2155
Willy Tarreau68a897b2009-12-03 23:28:34 +01002156 if (!curproxy->cookie_domain) {
2157 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2158 } else {
2159 /* one domain was already specified, add another one by
2160 * building the string which will be returned along with
2161 * the cookie.
2162 */
2163 char *new_ptr;
2164 int new_len = strlen(curproxy->cookie_domain) +
2165 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2166 new_ptr = malloc(new_len);
2167 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2168 free(curproxy->cookie_domain);
2169 curproxy->cookie_domain = new_ptr;
2170 }
Willy Tarreau31936852010-10-06 16:59:56 +02002171 cur_arg++;
2172 }
2173 else if (!strcmp(args[cur_arg], "maxidle")) {
2174 unsigned int maxidle;
2175 const char *res;
2176
2177 if (!*args[cur_arg + 1]) {
2178 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2179 file, linenum, args[cur_arg]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
2183
2184 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2185 if (res) {
2186 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2187 file, linenum, *res, args[cur_arg]);
2188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
2191 curproxy->cookie_maxidle = maxidle;
2192 cur_arg++;
2193 }
2194 else if (!strcmp(args[cur_arg], "maxlife")) {
2195 unsigned int maxlife;
2196 const char *res;
2197
2198 if (!*args[cur_arg + 1]) {
2199 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2200 file, linenum, args[cur_arg]);
2201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
2203 }
2204
2205 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2206 if (res) {
2207 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2208 file, linenum, *res, args[cur_arg]);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
2212 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002213 cur_arg++;
2214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002216 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 +02002217 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 }
2221 cur_arg++;
2222 }
Willy Tarreau67402132012-05-31 20:40:20 +02002223 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2225 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }
2228
Willy Tarreau67402132012-05-31 20:40:20 +02002229 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2231 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002234
Willy Tarreau67402132012-05-31 20:40:20 +02002235 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002236 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2237 file, linenum);
2238 err_code |= ERR_ALERT | ERR_FATAL;
2239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002241 else if (!strcmp(args[0], "persist")) { /* persist */
2242 if (*(args[1]) == 0) {
2243 Alert("parsing [%s:%d] : missing persist method.\n",
2244 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002247 }
2248
2249 if (!strncmp(args[1], "rdp-cookie", 10)) {
2250 curproxy->options2 |= PR_O2_RDPC_PRST;
2251
Emeric Brunb982a3d2010-01-04 15:45:53 +01002252 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002253 const char *beg, *end;
2254
2255 beg = args[1] + 11;
2256 end = strchr(beg, ')');
2257
2258 if (!end || end == beg) {
2259 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002263 }
2264
2265 free(curproxy->rdp_cookie_name);
2266 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2267 curproxy->rdp_cookie_len = end-beg;
2268 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002269 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002270 free(curproxy->rdp_cookie_name);
2271 curproxy->rdp_cookie_name = strdup("msts");
2272 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2273 }
2274 else { /* syntax */
2275 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2276 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002279 }
2280 }
2281 else {
2282 Alert("parsing [%s:%d] : unknown persist method.\n",
2283 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002286 }
2287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002289 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002291 if (curproxy == &defproxy) {
2292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
2295 }
2296
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002299
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002301 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002307 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 curproxy->appsession_name = strdup(args[1]);
2309 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2310 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002311 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2312 if (err) {
2313 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2314 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002317 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002318 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002319
Willy Tarreau51041c72007-09-09 21:56:53 +02002320 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_ABORT;
2323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002325
2326 cur_arg = 6;
2327 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002328 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2329 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002332 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002333 } else if (!strcmp(args[cur_arg], "prefix")) {
2334 curproxy->options2 |= PR_O2_AS_PFX;
2335 } else if (!strcmp(args[cur_arg], "mode")) {
2336 if (!*args[cur_arg + 1]) {
2337 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2338 file, linenum, args[0], args[cur_arg]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342
2343 cur_arg++;
2344 if (!strcmp(args[cur_arg], "query-string")) {
2345 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2346 curproxy->options2 |= PR_O2_AS_M_QS;
2347 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2348 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2349 curproxy->options2 |= PR_O2_AS_M_PP;
2350 } else {
2351 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
2354 }
2355 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002356 cur_arg++;
2357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 } /* Url App Session */
2359 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002360 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002362
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002364 if (curproxy == &defproxy) {
2365 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 if (*(args[4]) == 0) {
2371 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2372 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002376 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 curproxy->capture_name = strdup(args[2]);
2378 curproxy->capture_namelen = strlen(curproxy->capture_name);
2379 curproxy->capture_len = atol(args[4]);
2380 if (curproxy->capture_len >= CAPTURE_LEN) {
2381 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2382 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 curproxy->capture_len = CAPTURE_LEN - 1;
2385 }
2386 curproxy->to_log |= LW_COOKIE;
2387 }
2388 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2389 struct cap_hdr *hdr;
2390
2391 if (curproxy == &defproxy) {
2392 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 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396
2397 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2398 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2399 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
2403
2404 hdr = calloc(sizeof(struct cap_hdr), 1);
2405 hdr->next = curproxy->req_cap;
2406 hdr->name = strdup(args[3]);
2407 hdr->namelen = strlen(args[3]);
2408 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002409 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 hdr->index = curproxy->nb_req_cap++;
2411 curproxy->req_cap = hdr;
2412 curproxy->to_log |= LW_REQHDR;
2413 }
2414 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2415 struct cap_hdr *hdr;
2416
2417 if (curproxy == &defproxy) {
2418 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 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422
2423 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2424 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2425 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429 hdr = calloc(sizeof(struct cap_hdr), 1);
2430 hdr->next = curproxy->rsp_cap;
2431 hdr->name = strdup(args[3]);
2432 hdr->namelen = strlen(args[3]);
2433 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002434 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 hdr->index = curproxy->nb_rsp_cap++;
2436 curproxy->rsp_cap = hdr;
2437 curproxy->to_log |= LW_RSPHDR;
2438 }
2439 else {
2440 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2441 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
2445 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 if (*(args[1]) == 0) {
2451 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2452 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 curproxy->conn_retries = atol(args[1]);
2457 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002458 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002459 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002460
2461 if (curproxy == &defproxy) {
2462 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
Willy Tarreauff011f22011-01-06 17:51:27 +01002467 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 +01002468 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2469 file, linenum, args[0]);
2470 err_code |= ERR_WARN;
2471 }
2472
Willy Tarreauff011f22011-01-06 17:51:27 +01002473 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002474
Willy Tarreauff011f22011-01-06 17:51:27 +01002475 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002476 err_code |= ERR_ALERT | ERR_ABORT;
2477 goto out;
2478 }
2479
Willy Tarreauff011f22011-01-06 17:51:27 +01002480 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2481 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002482 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002483 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2484 /* set the header name and length into the proxy structure */
2485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2486 err_code |= ERR_WARN;
2487
2488 if (!*args[1]) {
2489 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2490 file, linenum, args[0]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
2495 /* set the desired header name */
2496 free(curproxy->server_id_hdr_name);
2497 curproxy->server_id_hdr_name = strdup(args[1]);
2498 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2499 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002500 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002501 if (curproxy == &defproxy) {
2502 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002505 }
2506
Willy Tarreauef6494c2010-01-28 17:12:36 +01002507 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002508 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002512 }
2513
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002514 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2515 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2516 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002519 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002520
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002521 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002522 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002523 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002524 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002525 struct redirect_rule *rule;
2526 int cur_arg;
2527 int type = REDIRECT_TYPE_NONE;
2528 int code = 302;
2529 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002530 char *cookie = NULL;
2531 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002532 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533
Cyril Bonté99ed3272010-01-24 23:29:44 +01002534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002540 cur_arg = 1;
2541 while (*(args[cur_arg])) {
2542 if (!strcmp(args[cur_arg], "location")) {
2543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2545 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002548 }
2549
2550 type = REDIRECT_TYPE_LOCATION;
2551 cur_arg++;
2552 destination = args[cur_arg];
2553 }
2554 else if (!strcmp(args[cur_arg], "prefix")) {
2555 if (!*args[cur_arg + 1]) {
2556 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2557 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002560 }
2561
2562 type = REDIRECT_TYPE_PREFIX;
2563 cur_arg++;
2564 destination = args[cur_arg];
2565 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002566 else if (!strcmp(args[cur_arg], "scheme")) {
2567 if (!*args[cur_arg + 1]) {
2568 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2569 file, linenum, args[0], args[cur_arg]);
2570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
2572 }
2573
2574 type = REDIRECT_TYPE_SCHEME;
2575 cur_arg++;
2576 destination = args[cur_arg];
2577 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002578 else if (!strcmp(args[cur_arg], "set-cookie")) {
2579 if (!*args[cur_arg + 1]) {
2580 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2581 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002584 }
2585
2586 cur_arg++;
2587 cookie = args[cur_arg];
2588 cookie_set = 1;
2589 }
2590 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2591 if (!*args[cur_arg + 1]) {
2592 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2593 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002596 }
2597
2598 cur_arg++;
2599 cookie = args[cur_arg];
2600 cookie_set = 0;
2601 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002602 else if (!strcmp(args[cur_arg],"code")) {
2603 if (!*args[cur_arg + 1]) {
2604 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 }
2609 cur_arg++;
2610 code = atol(args[cur_arg]);
2611 if (code < 301 || code > 303) {
2612 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2613 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002616 }
2617 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002618 else if (!strcmp(args[cur_arg],"drop-query")) {
2619 flags |= REDIRECT_FLAG_DROP_QS;
2620 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002621 else if (!strcmp(args[cur_arg],"append-slash")) {
2622 flags |= REDIRECT_FLAG_APPEND_SLASH;
2623 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002624 else if (strcmp(args[cur_arg], "if") == 0 ||
2625 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002626 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002627 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002628 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2629 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002633 break;
2634 }
2635 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002636 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 +02002637 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002640 }
2641 cur_arg++;
2642 }
2643
2644 if (type == REDIRECT_TYPE_NONE) {
2645 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 }
2650
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002651 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2652 rule->cond = cond;
2653 rule->rdr_str = strdup(destination);
2654 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002655 if (cookie) {
2656 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002657 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002658 */
2659 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002660 if (cookie_set) {
2661 rule->cookie_str = malloc(rule->cookie_len + 10);
2662 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2663 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2664 rule->cookie_len += 9;
2665 } else {
2666 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002667 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002668 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2669 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002670 }
2671 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 rule->type = type;
2673 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002674 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002675 LIST_INIT(&rule->list);
2676 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002677 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2678 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002680 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002681 struct switching_rule *rule;
2682
Willy Tarreaub099aca2008-10-12 17:26:37 +02002683 if (curproxy == &defproxy) {
2684 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002687 }
2688
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691
2692 if (*(args[1]) == 0) {
2693 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002696 }
2697
Willy Tarreauef6494c2010-01-28 17:12:36 +01002698 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2700 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703 }
2704
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002705 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2706 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2707 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002710 }
2711
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002712 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002713
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2715 rule->cond = cond;
2716 rule->be.name = strdup(args[1]);
2717 LIST_INIT(&rule->list);
2718 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2719 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002720 else if (strcmp(args[0], "use-server") == 0) {
2721 struct server_rule *rule;
2722
2723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
2729 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2730 err_code |= ERR_WARN;
2731
2732 if (*(args[1]) == 0) {
2733 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737
2738 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2739 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2740 file, linenum, args[0]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002745 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2746 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2747 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
2751
2752 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2753
2754 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2755 rule->cond = cond;
2756 rule->srv.name = strdup(args[1]);
2757 LIST_INIT(&rule->list);
2758 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2759 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2760 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002761 else if ((!strcmp(args[0], "force-persist")) ||
2762 (!strcmp(args[0], "ignore-persist"))) {
2763 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002764
2765 if (curproxy == &defproxy) {
2766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770
2771 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2772 err_code |= ERR_WARN;
2773
Willy Tarreauef6494c2010-01-28 17:12:36 +01002774 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002775 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2776 file, linenum, args[0]);
2777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
2779 }
2780
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002781 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2782 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2783 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
2786 }
2787
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002788 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002789
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002790 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002791 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002792 if (!strcmp(args[0], "force-persist")) {
2793 rule->type = PERSIST_TYPE_FORCE;
2794 } else {
2795 rule->type = PERSIST_TYPE_IGNORE;
2796 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002797 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002798 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002799 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002800 else if (!strcmp(args[0], "stick-table")) {
2801 int myidx = 1;
2802
Emeric Brun32da3c42010-09-23 18:39:19 +02002803 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002804 curproxy->table.type = (unsigned int)-1;
2805 while (*args[myidx]) {
2806 const char *err;
2807
2808 if (strcmp(args[myidx], "size") == 0) {
2809 myidx++;
2810 if (!*(args[myidx])) {
2811 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2812 file, linenum, args[myidx-1]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2817 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2818 file, linenum, *err, args[myidx-1]);
2819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
2821 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002822 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002824 else if (strcmp(args[myidx], "peers") == 0) {
2825 myidx++;
2826 if (!*(args[myidx])) {
2827 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2828 file, linenum, args[myidx-1]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832 curproxy->table.peers.name = strdup(args[myidx++]);
2833 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002834 else if (strcmp(args[myidx], "expire") == 0) {
2835 myidx++;
2836 if (!*(args[myidx])) {
2837 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2838 file, linenum, args[myidx-1]);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2843 if (err) {
2844 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2845 file, linenum, *err, args[myidx-1]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002850 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002851 }
2852 else if (strcmp(args[myidx], "nopurge") == 0) {
2853 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002854 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002855 }
2856 else if (strcmp(args[myidx], "type") == 0) {
2857 myidx++;
2858 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2859 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2860 file, linenum, args[myidx]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002864 /* myidx already points to next arg */
2865 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002866 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002867 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002868 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002869
2870 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002871 nw = args[myidx];
2872 while (*nw) {
2873 /* the "store" keyword supports a comma-separated list */
2874 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002875 sa = NULL; /* store arg */
2876 while (*nw && *nw != ',') {
2877 if (*nw == '(') {
2878 *nw = 0;
2879 sa = ++nw;
2880 while (*nw != ')') {
2881 if (!*nw) {
2882 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2883 file, linenum, args[0], cw);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887 nw++;
2888 }
2889 *nw = '\0';
2890 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002891 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002892 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002893 if (*nw)
2894 *nw++ = '\0';
2895 type = stktable_get_data_type(cw);
2896 if (type < 0) {
2897 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2898 file, linenum, args[0], cw);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
Willy Tarreauac782882010-06-20 10:41:54 +02002902
2903 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2904 switch (err) {
2905 case PE_NONE: break;
2906 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002907 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2908 file, linenum, args[0], cw);
2909 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002910 break;
2911
2912 case PE_ARG_MISSING:
2913 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2914 file, linenum, args[0], cw);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917
2918 case PE_ARG_NOT_USED:
2919 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2920 file, linenum, args[0], cw);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923
2924 default:
2925 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002929 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002930 }
2931 myidx++;
2932 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002933 else {
2934 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2935 file, linenum, args[myidx]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002939 }
2940
2941 if (!curproxy->table.size) {
2942 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2943 file, linenum);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
2947
2948 if (curproxy->table.type == (unsigned int)-1) {
2949 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2950 file, linenum);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954 }
2955 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002957 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 int myidx = 0;
2959 const char *name = NULL;
2960 int flags;
2961
2962 if (curproxy == &defproxy) {
2963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967
2968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2969 err_code |= ERR_WARN;
2970 goto out;
2971 }
2972
2973 myidx++;
2974 if ((strcmp(args[myidx], "store") == 0) ||
2975 (strcmp(args[myidx], "store-request") == 0)) {
2976 myidx++;
2977 flags = STK_IS_STORE;
2978 }
2979 else if (strcmp(args[myidx], "store-response") == 0) {
2980 myidx++;
2981 flags = STK_IS_STORE | STK_ON_RSP;
2982 }
2983 else if (strcmp(args[myidx], "match") == 0) {
2984 myidx++;
2985 flags = STK_IS_MATCH;
2986 }
2987 else if (strcmp(args[myidx], "on") == 0) {
2988 myidx++;
2989 flags = STK_IS_MATCH | STK_IS_STORE;
2990 }
2991 else {
2992 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996
2997 if (*(args[myidx]) == 0) {
2998 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003003 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003005 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009
3010 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003011 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003012 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3013 file, linenum, args[0], expr->fetch->kw);
3014 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003015 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003016 goto out;
3017 }
3018 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003019 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3021 file, linenum, args[0], expr->fetch->kw);
3022 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003023 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 goto out;
3025 }
3026 }
3027
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003028 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3029 if (expr->fetch->cap & SMP_CAP_L7)
3030 curproxy->acl_requires |= ACL_USE_L7_ANY;
3031
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 if (strcmp(args[myidx], "table") == 0) {
3033 myidx++;
3034 name = args[myidx++];
3035 }
3036
Willy Tarreauef6494c2010-01-28 17:12:36 +01003037 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003038 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3039 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3040 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003042 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 goto out;
3044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003046 else if (*(args[myidx])) {
3047 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3048 file, linenum, args[0], args[myidx]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003050 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003051 goto out;
3052 }
Emeric Brun97679e72010-09-23 17:56:44 +02003053 if (flags & STK_ON_RSP)
3054 err_code |= warnif_cond_requires_req(cond, file, linenum);
3055 else
3056 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003057
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3059 rule->cond = cond;
3060 rule->expr = expr;
3061 rule->flags = flags;
3062 rule->table.name = name ? strdup(name) : NULL;
3063 LIST_INIT(&rule->list);
3064 if (flags & STK_ON_RSP)
3065 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3066 else
3067 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003072
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3074 curproxy->uri_auth = NULL; /* we must detach from the default config */
3075
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003076 if (!*args[1]) {
3077 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003078 } else if (!strcmp(args[1], "admin")) {
3079 struct stats_admin_rule *rule;
3080
3081 if (curproxy == &defproxy) {
3082 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
3087 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3088 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3089 err_code |= ERR_ALERT | ERR_ABORT;
3090 goto out;
3091 }
3092
3093 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3094 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3095 file, linenum, args[0], args[1]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003099 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3100 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3101 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
3106 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3107
3108 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3109 rule->cond = cond;
3110 LIST_INIT(&rule->list);
3111 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 } else if (!strcmp(args[1], "uri")) {
3113 if (*(args[2]) == 0) {
3114 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_ABORT;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 }
3122 } else if (!strcmp(args[1], "realm")) {
3123 if (*(args[2]) == 0) {
3124 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003132 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003133 unsigned interval;
3134
3135 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3136 if (err) {
3137 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3138 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003141 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003145 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003147 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003148
3149 if (curproxy == &defproxy) {
3150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154
3155 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3156 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3157 err_code |= ERR_ALERT | ERR_ABORT;
3158 goto out;
3159 }
3160
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3162 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003163 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3164 file, linenum, args[0]);
3165 err_code |= ERR_WARN;
3166 }
3167
Willy Tarreauff011f22011-01-06 17:51:27 +01003168 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169
Willy Tarreauff011f22011-01-06 17:51:27 +01003170 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
3173 }
3174
Willy Tarreauff011f22011-01-06 17:51:27 +01003175 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3176 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 } else if (!strcmp(args[1], "auth")) {
3179 if (*(args[2]) == 0) {
3180 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
3188 } else if (!strcmp(args[1], "scope")) {
3189 if (*(args[2]) == 0) {
3190 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 }
3198 } else if (!strcmp(args[1], "enable")) {
3199 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_ABORT;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003204 } else if (!strcmp(args[1], "hide-version")) {
3205 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3206 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_ABORT;
3208 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003209 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003210 } else if (!strcmp(args[1], "show-legends")) {
3211 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3212 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3213 err_code |= ERR_ALERT | ERR_ABORT;
3214 goto out;
3215 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003216 } else if (!strcmp(args[1], "show-node")) {
3217
3218 if (*args[2]) {
3219 int i;
3220 char c;
3221
3222 for (i=0; args[2][i]; i++) {
3223 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003224 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3225 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003226 break;
3227 }
3228
3229 if (!i || args[2][i]) {
3230 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3231 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3232 file, linenum, args[0], args[1]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236 }
3237
3238 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
3242 }
3243 } else if (!strcmp(args[1], "show-desc")) {
3244 char *desc = NULL;
3245
3246 if (*args[2]) {
3247 int i, len=0;
3248 char *d;
3249
3250 for(i=2; *args[i]; i++)
3251 len += strlen(args[i])+1;
3252
3253 desc = d = (char *)calloc(1, len);
3254
3255 d += sprintf(d, "%s", args[2]);
3256 for(i=3; *args[i]; i++)
3257 d += sprintf(d, " %s", args[i]);
3258 }
3259
3260 if (!*args[2] && !global.desc)
3261 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3262 file, linenum, args[1]);
3263 else {
3264 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3265 free(desc);
3266 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3267 err_code |= ERR_ALERT | ERR_ABORT;
3268 goto out;
3269 }
3270 free(desc);
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003273stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003274 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 +01003275 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 }
3280 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003281 int optnum;
3282
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003283 if (*(args[1]) == '\0') {
3284 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003289
3290 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3291 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003292 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3293 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3294 file, linenum, cfg_opts[optnum].name);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
Willy Tarreau93893792009-07-23 13:19:11 +02003298 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3299 err_code |= ERR_WARN;
3300 goto out;
3301 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003302
Willy Tarreau3842f002009-06-14 11:39:52 +02003303 curproxy->no_options &= ~cfg_opts[optnum].val;
3304 curproxy->options &= ~cfg_opts[optnum].val;
3305
3306 switch (kwm) {
3307 case KWM_STD:
3308 curproxy->options |= cfg_opts[optnum].val;
3309 break;
3310 case KWM_NO:
3311 curproxy->no_options |= cfg_opts[optnum].val;
3312 break;
3313 case KWM_DEF: /* already cleared */
3314 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003315 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003316
Willy Tarreau93893792009-07-23 13:19:11 +02003317 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318 }
3319 }
3320
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003321 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3322 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003323 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3324 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3325 file, linenum, cfg_opts2[optnum].name);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
Willy Tarreau93893792009-07-23 13:19:11 +02003329 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3330 err_code |= ERR_WARN;
3331 goto out;
3332 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003333
Willy Tarreau3842f002009-06-14 11:39:52 +02003334 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3335 curproxy->options2 &= ~cfg_opts2[optnum].val;
3336
3337 switch (kwm) {
3338 case KWM_STD:
3339 curproxy->options2 |= cfg_opts2[optnum].val;
3340 break;
3341 case KWM_NO:
3342 curproxy->no_options2 |= cfg_opts2[optnum].val;
3343 break;
3344 case KWM_DEF: /* already cleared */
3345 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003346 }
Willy Tarreau93893792009-07-23 13:19:11 +02003347 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003348 }
3349 }
3350
Willy Tarreau3842f002009-06-14 11:39:52 +02003351 if (kwm != KWM_STD) {
3352 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003353 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003356 }
3357
Emeric Brun3a058f32009-06-30 18:26:00 +02003358 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003359 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003361 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003362 if (*(args[2]) != '\0') {
3363 if (!strcmp(args[2], "clf")) {
3364 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003365 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 } else {
3367 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003370 }
3371 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003372 if (curproxy->logformat_string != default_http_log_format &&
3373 curproxy->logformat_string != default_tcp_log_format &&
3374 curproxy->logformat_string != clf_http_log_format)
3375 free(curproxy->logformat_string);
3376 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003377 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003378 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003380 if (curproxy->logformat_string != default_http_log_format &&
3381 curproxy->logformat_string != default_tcp_log_format &&
3382 curproxy->logformat_string != clf_http_log_format)
3383 free(curproxy->logformat_string);
3384 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 else if (!strcmp(args[1], "tcpka")) {
3387 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003388 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003390
3391 if (curproxy->cap & PR_CAP_FE)
3392 curproxy->options |= PR_O_TCP_CLI_KA;
3393 if (curproxy->cap & PR_CAP_BE)
3394 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
3396 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_WARN;
3399
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003401 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003402 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003403 curproxy->options2 &= ~PR_O2_CHK_ANY;
3404 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 if (!*args[2]) { /* no argument */
3406 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3407 curproxy->check_len = strlen(DEF_CHECK_REQ);
3408 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003409 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 curproxy->check_req = (char *)malloc(reqlen);
3411 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003412 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003414 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 if (*args[4])
3416 reqlen += strlen(args[4]);
3417 else
3418 reqlen += strlen("HTTP/1.0");
3419
3420 curproxy->check_req = (char *)malloc(reqlen);
3421 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003422 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003424 }
3425 else if (!strcmp(args[1], "ssl-hello-chk")) {
3426 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003429
Willy Tarreaua534fea2008-08-03 12:19:50 +02003430 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003431 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003432 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003433 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Willy Tarreau23677902007-05-08 23:50:35 +02003435 else if (!strcmp(args[1], "smtpchk")) {
3436 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003437 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003438 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003439 curproxy->options2 &= ~PR_O2_CHK_ANY;
3440 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003441
3442 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3443 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3444 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3445 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3446 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3447 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3448 curproxy->check_req = (char *)malloc(reqlen);
3449 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3450 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3451 } else {
3452 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3453 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3454 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3455 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3456 }
3457 }
3458 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003459 else if (!strcmp(args[1], "pgsql-check")) {
3460 /* use PostgreSQL request to check servers' health */
3461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3462 err_code |= ERR_WARN;
3463
3464 free(curproxy->check_req);
3465 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003466 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003467 curproxy->options2 |= PR_O2_PGSQL_CHK;
3468
3469 if (*(args[2])) {
3470 int cur_arg = 2;
3471
3472 while (*(args[cur_arg])) {
3473 if (strcmp(args[cur_arg], "user") == 0) {
3474 char * packet;
3475 uint32_t packet_len;
3476 uint32_t pv;
3477
3478 /* suboption header - needs additional argument for it */
3479 if (*(args[cur_arg+1]) == 0) {
3480 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3481 file, linenum, args[0], args[1], args[cur_arg]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
3484 }
3485
3486 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3487 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3488 pv = htonl(0x30000); /* protocol version 3.0 */
3489
3490 packet = (char*) calloc(1, packet_len);
3491
3492 memcpy(packet + 4, &pv, 4);
3493
3494 /* copy "user" */
3495 memcpy(packet + 8, "user", 4);
3496
3497 /* copy username */
3498 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3499
3500 free(curproxy->check_req);
3501 curproxy->check_req = packet;
3502 curproxy->check_len = packet_len;
3503
3504 packet_len = htonl(packet_len);
3505 memcpy(packet, &packet_len, 4);
3506 cur_arg += 2;
3507 } else {
3508 /* unknown suboption - catchall */
3509 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3510 file, linenum, args[0], args[1]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514 } /* end while loop */
3515 }
3516 }
3517
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003518 else if (!strcmp(args[1], "redis-check")) {
3519 /* use REDIS PING request to check servers' health */
3520 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3521 err_code |= ERR_WARN;
3522
3523 free(curproxy->check_req);
3524 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003525 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003526 curproxy->options2 |= PR_O2_REDIS_CHK;
3527
3528 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3529 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3530 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3531 }
3532
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003533 else if (!strcmp(args[1], "mysql-check")) {
3534 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003535 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3536 err_code |= ERR_WARN;
3537
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003538 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003539 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003540 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003541 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003542
3543 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3544 * const char mysql40_client_auth_pkt[] = {
3545 * "\x0e\x00\x00" // packet length
3546 * "\x01" // packet number
3547 * "\x00\x00" // client capabilities
3548 * "\x00\x00\x01" // max packet
3549 * "haproxy\x00" // username (null terminated string)
3550 * "\x00" // filler (always 0x00)
3551 * "\x01\x00\x00" // packet length
3552 * "\x00" // packet number
3553 * "\x01" // COM_QUIT command
3554 * };
3555 */
3556
3557 if (*(args[2])) {
3558 int cur_arg = 2;
3559
3560 while (*(args[cur_arg])) {
3561 if (strcmp(args[cur_arg], "user") == 0) {
3562 char *mysqluser;
3563 int packetlen, reqlen, userlen;
3564
3565 /* suboption header - needs additional argument for it */
3566 if (*(args[cur_arg+1]) == 0) {
3567 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3568 file, linenum, args[0], args[1], args[cur_arg]);
3569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
3571 }
3572 mysqluser = args[cur_arg + 1];
3573 userlen = strlen(mysqluser);
3574 packetlen = userlen + 7;
3575 reqlen = packetlen + 9;
3576
3577 free(curproxy->check_req);
3578 curproxy->check_req = (char *)calloc(1, reqlen);
3579 curproxy->check_len = reqlen;
3580
3581 snprintf(curproxy->check_req, 4, "%c%c%c",
3582 ((unsigned char) packetlen & 0xff),
3583 ((unsigned char) (packetlen >> 8) & 0xff),
3584 ((unsigned char) (packetlen >> 16) & 0xff));
3585
3586 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003587 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003588 curproxy->check_req[8] = 1;
3589 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3590 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3591 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3592 cur_arg += 2;
3593 } else {
3594 /* unknown suboption - catchall */
3595 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3596 file, linenum, args[0], args[1]);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600 } /* end while loop */
3601 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003602 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003603 else if (!strcmp(args[1], "ldap-check")) {
3604 /* use LDAP request to check servers' health */
3605 free(curproxy->check_req);
3606 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003607 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003608 curproxy->options2 |= PR_O2_LDAP_CHK;
3609
3610 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3611 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3612 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3613 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003614 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003615 int cur_arg;
3616
3617 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3618 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003619 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003620
Willy Tarreau87cf5142011-08-19 22:57:24 +02003621 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003622
3623 free(curproxy->fwdfor_hdr_name);
3624 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3625 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3626
3627 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3628 cur_arg = 2;
3629 while (*(args[cur_arg])) {
3630 if (!strcmp(args[cur_arg], "except")) {
3631 /* suboption except - needs additional argument for it */
3632 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3633 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3634 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003637 }
3638 /* flush useless bits */
3639 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003640 cur_arg += 2;
3641 } else if (!strcmp(args[cur_arg], "header")) {
3642 /* suboption header - needs additional argument for it */
3643 if (*(args[cur_arg+1]) == 0) {
3644 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3645 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003648 }
3649 free(curproxy->fwdfor_hdr_name);
3650 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3651 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3652 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003653 } else if (!strcmp(args[cur_arg], "if-none")) {
3654 curproxy->options &= ~PR_O_FF_ALWAYS;
3655 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003656 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003657 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003658 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003659 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003663 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003664 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003665 else if (!strcmp(args[1], "originalto")) {
3666 int cur_arg;
3667
3668 /* insert x-original-to field, but not for the IP address listed as an except.
3669 * set default options (ie: bitfield, header name, etc)
3670 */
3671
3672 curproxy->options |= PR_O_ORGTO;
3673
3674 free(curproxy->orgto_hdr_name);
3675 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3676 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3677
Willy Tarreau87cf5142011-08-19 22:57:24 +02003678 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003679 cur_arg = 2;
3680 while (*(args[cur_arg])) {
3681 if (!strcmp(args[cur_arg], "except")) {
3682 /* suboption except - needs additional argument for it */
3683 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3684 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3685 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003688 }
3689 /* flush useless bits */
3690 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3691 cur_arg += 2;
3692 } else if (!strcmp(args[cur_arg], "header")) {
3693 /* suboption header - needs additional argument for it */
3694 if (*(args[cur_arg+1]) == 0) {
3695 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3696 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003699 }
3700 free(curproxy->orgto_hdr_name);
3701 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3702 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3703 cur_arg += 2;
3704 } else {
3705 /* unknown suboption - catchall */
3706 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3707 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003710 }
3711 } /* end while loop */
3712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 else {
3714 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 }
Willy Tarreau93893792009-07-23 13:19:11 +02003718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003720 else if (!strcmp(args[0], "default_backend")) {
3721 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003723
3724 if (*(args[1]) == 0) {
3725 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003729 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003730 curproxy->defbe.name = strdup(args[1]);
3731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003735
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003736 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 /* enable reconnections to dispatch */
3740 curproxy->options |= PR_O_REDISP;
3741 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003742 else if (!strcmp(args[0], "http-check")) {
3743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003745
3746 if (strcmp(args[1], "disable-on-404") == 0) {
3747 /* enable a graceful server shutdown on an HTTP 404 response */
3748 curproxy->options |= PR_O_DISABLE404;
3749 }
Willy Tarreauef781042010-01-27 11:53:01 +01003750 else if (strcmp(args[1], "send-state") == 0) {
3751 /* enable emission of the apparent state of a server in HTTP checks */
3752 curproxy->options2 |= PR_O2_CHK_SNDST;
3753 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003754 else if (strcmp(args[1], "expect") == 0) {
3755 const char *ptr_arg;
3756 int cur_arg;
3757
3758 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3759 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763
3764 cur_arg = 2;
3765 /* consider exclamation marks, sole or at the beginning of a word */
3766 while (*(ptr_arg = args[cur_arg])) {
3767 while (*ptr_arg == '!') {
3768 curproxy->options2 ^= PR_O2_EXP_INV;
3769 ptr_arg++;
3770 }
3771 if (*ptr_arg)
3772 break;
3773 cur_arg++;
3774 }
3775 /* now ptr_arg points to the beginning of a word past any possible
3776 * exclamation mark, and cur_arg is the argument which holds this word.
3777 */
3778 if (strcmp(ptr_arg, "status") == 0) {
3779 if (!*(args[cur_arg + 1])) {
3780 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3781 file, linenum, args[0], args[1], ptr_arg);
3782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
3784 }
3785 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003786 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003787 curproxy->expect_str = strdup(args[cur_arg + 1]);
3788 }
3789 else if (strcmp(ptr_arg, "string") == 0) {
3790 if (!*(args[cur_arg + 1])) {
3791 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3792 file, linenum, args[0], args[1], ptr_arg);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003797 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003798 curproxy->expect_str = strdup(args[cur_arg + 1]);
3799 }
3800 else if (strcmp(ptr_arg, "rstatus") == 0) {
3801 if (!*(args[cur_arg + 1])) {
3802 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3803 file, linenum, args[0], args[1], ptr_arg);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
3807 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003808 free(curproxy->expect_str);
3809 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3810 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003811 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3812 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3813 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3814 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818 }
3819 else if (strcmp(ptr_arg, "rstring") == 0) {
3820 if (!*(args[cur_arg + 1])) {
3821 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3822 file, linenum, args[0], args[1], ptr_arg);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003827 free(curproxy->expect_str);
3828 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3829 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003830 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3831 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3832 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3833 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 }
3838 else {
3839 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3840 file, linenum, args[0], args[1], ptr_arg);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003845 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003846 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 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003849 }
3850 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003851 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003852 if (curproxy == &defproxy) {
3853 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003856 }
3857
Willy Tarreaub80c2302007-11-30 20:51:32 +01003858 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003860
3861 if (strcmp(args[1], "fail") == 0) {
3862 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003863 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003864 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3865 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003868 }
3869
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003870 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3871 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3872 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 }
3876 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3877 }
3878 else {
3879 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003882 }
3883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884#ifdef TPROXY
3885 else if (!strcmp(args[0], "transparent")) {
3886 /* enable transparent proxy connections */
3887 curproxy->options |= PR_O_TRANSP;
3888 }
3889#endif
3890 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003893
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 if (*(args[1]) == 0) {
3895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 }
3899 curproxy->maxconn = atol(args[1]);
3900 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003901 else if (!strcmp(args[0], "backlog")) { /* backlog */
3902 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003904
3905 if (*(args[1]) == 0) {
3906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003909 }
3910 curproxy->backlog = atol(args[1]);
3911 }
Willy Tarreau86034312006-12-29 00:10:33 +01003912 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915
Willy Tarreau86034312006-12-29 00:10:33 +01003916 if (*(args[1]) == 0) {
3917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003920 }
3921 curproxy->fullconn = atol(args[1]);
3922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3924 if (*(args[1]) == 0) {
3925 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003929 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3930 if (err) {
3931 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3932 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003935 }
3936 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 }
3938 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003939 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 if (curproxy == &defproxy) {
3941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003947
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 if (strchr(args[1], ':') == NULL) {
3949 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003953 sk = str2sa(args[1]);
3954 if (!sk) {
3955 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003960 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
3962 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003966 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3967 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003972 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3974 err_code |= ERR_WARN;
3975
3976 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3977 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3978 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3979 }
3980 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3981 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3982 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3983 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003984 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3985 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3986 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3987 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003988 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003989 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
3993 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003996 char *rport, *raddr;
3997 short realport = 0;
3998 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004000 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004005 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004006 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007
4008 if (!*args[2]) {
4009 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004014
4015 err = invalid_char(args[1]);
4016 if (err) {
4017 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4018 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004021 }
4022
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004023 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004024 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004025
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004026 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4027 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4028 err_code |= ERR_ALERT | ERR_ABORT;
4029 goto out;
4030 }
4031
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004032 /* the servers are linked backwards first */
4033 newsrv->next = curproxy->srv;
4034 curproxy->srv = newsrv;
4035 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004036 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004037 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004039 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004040 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041 LIST_INIT(&newsrv->pendconns);
4042 do_check = 0;
4043 newsrv->state = SRV_RUNNING; /* early server setup */
4044 newsrv->last_change = now.tv_sec;
4045 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004047 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004048 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004049 * - IP: => port=+0, relative
4050 * - IP:N => port=N, absolute
4051 * - IP:+N => port=+N, relative
4052 * - IP:-N => port=-N, relative
4053 */
4054 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004055 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004056 if (rport) {
4057 *rport++ = 0;
4058 realport = atol(rport);
4059 if (!isdigit((unsigned char)*rport))
4060 newsrv->state |= SRV_MAPPORTS;
4061 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063
Willy Tarreaufab5a432011-03-04 15:31:53 +01004064 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004065 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004066 if (!sk) {
4067 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
4070 }
4071 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004072 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4073 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004074
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004075 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004076 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4077 file, linenum, newsrv->addr.ss_family, args[2]);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004081 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004082
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004083 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004084 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004085 newsrv->inter = curproxy->defsrv.inter;
4086 newsrv->fastinter = curproxy->defsrv.fastinter;
4087 newsrv->downinter = curproxy->defsrv.downinter;
4088 newsrv->rise = curproxy->defsrv.rise;
4089 newsrv->fall = curproxy->defsrv.fall;
4090 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4091 newsrv->minconn = curproxy->defsrv.minconn;
4092 newsrv->maxconn = curproxy->defsrv.maxconn;
4093 newsrv->slowstart = curproxy->defsrv.slowstart;
4094 newsrv->onerror = curproxy->defsrv.onerror;
4095 newsrv->consecutive_errors_limit
4096 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004097#ifdef OPENSSL
4098 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4099#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 newsrv->uweight = newsrv->iweight
4101 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105 cur_arg = 3;
4106 } else {
4107 newsrv = &curproxy->defsrv;
4108 cur_arg = 1;
4109 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004110
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004112 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 newsrv->cookie = strdup(args[cur_arg + 1]);
4114 newsrv->cklen = strlen(args[cur_arg + 1]);
4115 cur_arg += 2;
4116 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004117 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004118 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4119 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4120 cur_arg += 2;
4121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004123 if (!*args[cur_arg + 1]) {
4124 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4125 file, linenum, args[cur_arg]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004131 if (newsrv->rise <= 0) {
4132 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4133 file, linenum, args[cur_arg]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137
Willy Tarreau96839092010-03-29 10:02:24 +02004138 if (newsrv->health)
4139 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 cur_arg += 2;
4141 }
4142 else if (!strcmp(args[cur_arg], "fall")) {
4143 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004144
4145 if (!*args[cur_arg + 1]) {
4146 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4147 file, linenum, args[cur_arg]);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151
4152 if (newsrv->fall <= 0) {
4153 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4154 file, linenum, args[cur_arg]);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
4158
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 cur_arg += 2;
4160 }
4161 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004162 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4163 if (err) {
4164 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4165 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004168 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004169 if (val <= 0) {
4170 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4171 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004174 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004175 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 cur_arg += 2;
4177 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004178 else if (!strcmp(args[cur_arg], "fastinter")) {
4179 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4180 if (err) {
4181 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4182 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004185 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004186 if (val <= 0) {
4187 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4188 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004191 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004192 newsrv->fastinter = val;
4193 cur_arg += 2;
4194 }
4195 else if (!strcmp(args[cur_arg], "downinter")) {
4196 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4197 if (err) {
4198 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4199 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004202 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004203 if (val <= 0) {
4204 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4205 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004208 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004209 newsrv->downinter = val;
4210 cur_arg += 2;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004213 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004214 if (!sk) {
4215 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004219 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004220 cur_arg += 2;
4221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004223 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 cur_arg += 2;
4225 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004226 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 newsrv->state |= SRV_BACKUP;
4228 cur_arg ++;
4229 }
Simon Hormanfa461682011-06-25 09:39:49 +09004230 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4231 newsrv->state |= SRV_NON_STICK;
4232 cur_arg ++;
4233 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004234 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4235 newsrv->state |= SRV_SEND_PROXY;
4236 cur_arg ++;
4237 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004238 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4239 newsrv->check.send_proxy = 1;
4240 cur_arg ++;
4241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 else if (!strcmp(args[cur_arg], "weight")) {
4243 int w;
4244 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004245 if (w < 0 || w > 256) {
4246 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004251 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 cur_arg += 2;
4253 }
4254 else if (!strcmp(args[cur_arg], "minconn")) {
4255 newsrv->minconn = atol(args[cur_arg + 1]);
4256 cur_arg += 2;
4257 }
4258 else if (!strcmp(args[cur_arg], "maxconn")) {
4259 newsrv->maxconn = atol(args[cur_arg + 1]);
4260 cur_arg += 2;
4261 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004262 else if (!strcmp(args[cur_arg], "maxqueue")) {
4263 newsrv->maxqueue = atol(args[cur_arg + 1]);
4264 cur_arg += 2;
4265 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004266 else if (!strcmp(args[cur_arg], "slowstart")) {
4267 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004268 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004269 if (err) {
4270 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4271 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004274 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004275 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004276 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4277 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004280 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004281 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004282 cur_arg += 2;
4283 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004284 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004285
4286 if (!*args[cur_arg + 1]) {
4287 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4288 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004291 }
4292
4293 newsrv->trackit = strdup(args[cur_arg + 1]);
4294
4295 cur_arg += 2;
4296 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004297 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 global.maxsock++;
4299 do_check = 1;
4300 cur_arg += 1;
4301 }
Willy Tarreau96839092010-03-29 10:02:24 +02004302 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4303 newsrv->state |= SRV_MAINTAIN;
4304 newsrv->state &= ~SRV_RUNNING;
4305 newsrv->health = 0;
4306 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004307 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004308 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004309 if (!strcmp(args[cur_arg + 1], "none"))
4310 newsrv->observe = HANA_OBS_NONE;
4311 else if (!strcmp(args[cur_arg + 1], "layer4"))
4312 newsrv->observe = HANA_OBS_LAYER4;
4313 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4314 if (curproxy->mode != PR_MODE_HTTP) {
4315 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4316 file, linenum, args[cur_arg + 1]);
4317 err_code |= ERR_ALERT;
4318 }
4319 newsrv->observe = HANA_OBS_LAYER7;
4320 }
4321 else {
4322 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004323 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004324 file, linenum, args[cur_arg], args[cur_arg + 1]);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328
4329 cur_arg += 2;
4330 }
4331 else if (!strcmp(args[cur_arg], "on-error")) {
4332 if (!strcmp(args[cur_arg + 1], "fastinter"))
4333 newsrv->onerror = HANA_ONERR_FASTINTER;
4334 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4335 newsrv->onerror = HANA_ONERR_FAILCHK;
4336 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4337 newsrv->onerror = HANA_ONERR_SUDDTH;
4338 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4339 newsrv->onerror = HANA_ONERR_MARKDWN;
4340 else {
4341 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004342 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004343 file, linenum, args[cur_arg], args[cur_arg + 1]);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347
4348 cur_arg += 2;
4349 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004350 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4351 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4352 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4353 else {
4354 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4355 file, linenum, args[cur_arg], args[cur_arg + 1]);
4356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
4358 }
4359
4360 cur_arg += 2;
4361 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004362 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4363 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4364 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4365 else {
4366 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4367 file, linenum, args[cur_arg], args[cur_arg + 1]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
4372 cur_arg += 2;
4373 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004374 else if (!strcmp(args[cur_arg], "error-limit")) {
4375 if (!*args[cur_arg + 1]) {
4376 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4377 file, linenum, args[cur_arg]);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
4381
4382 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4383
4384 if (newsrv->consecutive_errors_limit <= 0) {
4385 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4386 file, linenum, args[cur_arg]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004390 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004391 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004392 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004393 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004394 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004395
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004397#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004398 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004399 file, linenum, "source", "usesrc");
4400#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004401 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004403#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 }
4407 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004408 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4409 if (!sk) {
4410 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
4413 }
4414 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004415
4416 if (port_low != port_high) {
4417 int i;
4418 if (port_low <= 0 || port_low > 65535 ||
4419 port_high <= 0 || port_high > 65535 ||
4420 port_low > port_high) {
4421 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4422 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
4424 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004425 }
4426 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4427 for (i = 0; i < newsrv->sport_range->size; i++)
4428 newsrv->sport_range->ports[i] = port_low + i;
4429 }
4430
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004432 while (*(args[cur_arg])) {
4433 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004434#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4435#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004436 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4437 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4438 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004441 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004442#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004444 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004445 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004448 }
4449 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004450 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004451 newsrv->state |= SRV_TPROXY_CLI;
4452 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004453 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004454 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004455 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4456 char *name, *end;
4457
4458 name = args[cur_arg+1] + 7;
4459 while (isspace(*name))
4460 name++;
4461
4462 end = name;
4463 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4464 end++;
4465
4466 newsrv->state &= ~SRV_TPROXY_MASK;
4467 newsrv->state |= SRV_TPROXY_DYN;
4468 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4469 newsrv->bind_hdr_len = end - name;
4470 memcpy(newsrv->bind_hdr_name, name, end - name);
4471 newsrv->bind_hdr_name[end-name] = '\0';
4472 newsrv->bind_hdr_occ = -1;
4473
4474 /* now look for an occurrence number */
4475 while (isspace(*end))
4476 end++;
4477 if (*end == ',') {
4478 end++;
4479 name = end;
4480 if (*end == '-')
4481 end++;
4482 while (isdigit(*end))
4483 end++;
4484 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4485 }
4486
4487 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4488 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4489 " occurrences values smaller than %d.\n",
4490 file, linenum, MAX_HDR_HISTORY);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004494 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004495 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004496 if (!sk) {
4497 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
4500 }
4501 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004502 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004503 }
4504 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004505#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004506 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004507#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004508 cur_arg += 2;
4509 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004510#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004511 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004512 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004515#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4516 } /* "usesrc" */
4517
4518 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4519#ifdef SO_BINDTODEVICE
4520 if (!*args[cur_arg + 1]) {
4521 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4522 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004523 err_code |= ERR_ALERT | ERR_FATAL;
4524 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 }
4526 if (newsrv->iface_name)
4527 free(newsrv->iface_name);
4528
4529 newsrv->iface_name = strdup(args[cur_arg + 1]);
4530 newsrv->iface_len = strlen(newsrv->iface_name);
4531 global.last_checks |= LSTCHK_NETADM;
4532#else
4533 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4534 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004537#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004538 cur_arg += 2;
4539 continue;
4540 }
4541 /* this keyword in not an option of "source" */
4542 break;
4543 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004545 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004546 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4547 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004552 static int srv_dumped;
4553 struct srv_kw *kw;
4554 char *err;
4555
4556 kw = srv_find_kw(args[cur_arg]);
4557 if (kw) {
4558 char *err = NULL;
4559 int code;
4560
4561 if (!kw->parse) {
4562 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4563 file, linenum, args[0], args[1], args[cur_arg]);
4564 cur_arg += 1 + kw->skip ;
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
4568
4569 if (defsrv && !kw->default_ok) {
4570 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4571 file, linenum, args[0], args[1], args[cur_arg]);
4572 cur_arg += 1 + kw->skip ;
4573 err_code |= ERR_ALERT;
4574 continue;
4575 }
4576
4577 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4578 err_code |= code;
4579
4580 if (code) {
4581 if (err && *err) {
4582 indent_msg(&err, 2);
4583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4584 }
4585 else
4586 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4587 file, linenum, args[0], args[1], args[cur_arg]);
4588 if (code & ERR_FATAL) {
4589 free(err);
4590 cur_arg += 1 + kw->skip;
4591 goto out;
4592 }
4593 }
4594 free(err);
4595 cur_arg += 1 + kw->skip;
4596 continue;
4597 }
4598
4599 err = NULL;
4600 if (!srv_dumped) {
4601 srv_dump_kws(&err);
4602 indent_msg(&err, 4);
4603 srv_dumped = 1;
4604 }
4605
4606 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4607 file, linenum, args[0], args[1], args[cur_arg],
4608 err ? " Registered keywords :" : "", err ? err : "");
4609 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004610
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 }
4614 }
4615
4616 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004617 if (newsrv->trackit) {
4618 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4619 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004622 }
4623
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004624 /* If neither a port nor an addr was specified and no check transport
4625 * layer is forced, then the transport layer used by the checks is the
4626 * same as for the production traffic. Otherwise we use raw_sock by
4627 * default, unless one is specified.
4628 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004629 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004630#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004631 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004632#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004633 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4634 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004635 /* try to get the port from check.addr if check.port not set */
4636 if (!newsrv->check.port)
4637 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004638
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004639 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4640 newsrv->check.port = realport; /* by default */
4641 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004642 /* not yet valid, because no port was set on
4643 * the server either. We'll check if we have
4644 * a known port on the first listener.
4645 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004646 struct listener *l;
4647
4648 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004649 newsrv->check.port = get_host_port(&l->addr);
4650 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004651 break;
4652 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004653 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004654 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4656 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004660
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004661 /* Allocate buffer for check requests... */
4662 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004663 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4664 err_code |= ERR_ALERT | ERR_ABORT;
4665 goto out;
4666 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004667 newsrv->check.bi->size = global.tune.chksize;
4668
4669 /* Allocate buffer for check responses... */
4670 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4671 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4672 err_code |= ERR_ALERT | ERR_ABORT;
4673 goto out;
4674 }
4675 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004676
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004677 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004678 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004679 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4680 err_code |= ERR_ALERT | ERR_ABORT;
4681 goto out;
4682 }
4683
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004684 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4685 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 newsrv->state |= SRV_CHECKED;
4687 }
4688
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004689 if (!defsrv) {
4690 if (newsrv->state & SRV_BACKUP)
4691 curproxy->srv_bck++;
4692 else
4693 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004694
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004695 newsrv->prev_state = newsrv->state;
4696 }
William Lallemanda73203e2012-03-12 12:48:57 +01004697 }
4698
4699 else if (strcmp(args[0], "unique-id-format") == 0) {
4700 if (!*(args[1])) {
4701 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4702 err_code |= ERR_ALERT | ERR_FATAL;
4703 goto out;
4704 }
William Lallemand3203ff42012-11-11 17:30:56 +01004705 if (*(args[2])) {
4706 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004710 free(curproxy->uniqueid_format_string);
4711 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004712 }
William Lallemanda73203e2012-03-12 12:48:57 +01004713
4714 else if (strcmp(args[0], "unique-id-header") == 0) {
4715 if (!*(args[1])) {
4716 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
4720 free(curproxy->header_unique_id);
4721 curproxy->header_unique_id = strdup(args[1]);
4722 }
4723
William Lallemand723b73a2012-02-08 16:37:49 +01004724 else if (strcmp(args[0], "log-format") == 0) {
4725 if (!*(args[1])) {
4726 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
William Lallemand3203ff42012-11-11 17:30:56 +01004730 if (*(args[2])) {
4731 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004735
4736 if (curproxy->logformat_string != default_http_log_format &&
4737 curproxy->logformat_string != default_tcp_log_format &&
4738 curproxy->logformat_string != clf_http_log_format)
4739 free(curproxy->logformat_string);
4740 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
William Lallemand723b73a2012-02-08 16:37:49 +01004742
William Lallemand0f99e342011-10-12 17:50:54 +02004743 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4744 /* delete previous herited or defined syslog servers */
4745 struct logsrv *back;
4746
4747 if (*(args[1]) != 0) {
4748 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
4752
William Lallemand723b73a2012-02-08 16:37:49 +01004753 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4754 LIST_DEL(&tmplogsrv->list);
4755 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004756 }
4757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004759 struct logsrv *logsrv;
4760
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004762 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004763 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004764 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004765 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004766 LIST_INIT(&node->list);
4767 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 }
4770 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004771
4772 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773
William Lallemand0f99e342011-10-12 17:50:54 +02004774 logsrv->facility = get_log_facility(args[2]);
4775 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 }
4781
William Lallemand0f99e342011-10-12 17:50:54 +02004782 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004784 logsrv->level = get_log_level(args[3]);
4785 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
4791 }
4792
William Lallemand0f99e342011-10-12 17:50:54 +02004793 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004794 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004795 logsrv->minlvl = get_log_level(args[4]);
4796 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004797 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
4800
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004801 }
4802 }
4803
Robert Tsai81ae1952007-12-05 10:47:29 +01004804 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004805 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004806 if (!sk) {
4807 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004808 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
William Lallemand0f99e342011-10-12 17:50:54 +02004812 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004813 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004814 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004815 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004816 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 }
William Lallemand0f99e342011-10-12 17:50:54 +02004820 logsrv->addr = *sk;
4821 if (!get_host_port(&logsrv->addr))
4822 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
William Lallemand0f99e342011-10-12 17:50:54 +02004824
4825 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else {
4828 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4829 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 }
4833 }
4834 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004835 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004836 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004837
Willy Tarreau977b8e42006-12-29 14:19:17 +01004838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004840
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004842 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4843 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004847
4848 /* we must first clear any optional default setting */
4849 curproxy->options &= ~PR_O_TPXY_MASK;
4850 free(curproxy->iface_name);
4851 curproxy->iface_name = NULL;
4852 curproxy->iface_len = 0;
4853
Willy Tarreaud5191e72010-02-09 20:50:45 +01004854 sk = str2sa(args[1]);
4855 if (!sk) {
4856 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859 }
4860 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004862
4863 cur_arg = 2;
4864 while (*(args[cur_arg])) {
4865 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004866#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4867#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4869 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4870 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004873 }
4874#endif
4875 if (!*args[cur_arg + 1]) {
4876 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4877 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004880 }
4881
4882 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004883 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004884 curproxy->options |= PR_O_TPXY_CLI;
4885 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004886 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004887 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004888 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4889 char *name, *end;
4890
4891 name = args[cur_arg+1] + 7;
4892 while (isspace(*name))
4893 name++;
4894
4895 end = name;
4896 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4897 end++;
4898
4899 curproxy->options &= ~PR_O_TPXY_MASK;
4900 curproxy->options |= PR_O_TPXY_DYN;
4901 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4902 curproxy->bind_hdr_len = end - name;
4903 memcpy(curproxy->bind_hdr_name, name, end - name);
4904 curproxy->bind_hdr_name[end-name] = '\0';
4905 curproxy->bind_hdr_occ = -1;
4906
4907 /* now look for an occurrence number */
4908 while (isspace(*end))
4909 end++;
4910 if (*end == ',') {
4911 end++;
4912 name = end;
4913 if (*end == '-')
4914 end++;
4915 while (isdigit(*end))
4916 end++;
4917 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4918 }
4919
4920 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4921 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4922 " occurrences values smaller than %d.\n",
4923 file, linenum, MAX_HDR_HISTORY);
4924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004927 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004928 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004929 if (!sk) {
4930 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
4933 }
4934 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004935 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004936 }
4937 global.last_checks |= LSTCHK_NETADM;
4938#if !defined(CONFIG_HAP_LINUX_TPROXY)
4939 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004940#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941#else /* no TPROXY support */
4942 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004943 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004946#endif
4947 cur_arg += 2;
4948 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004949 }
4950
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004951 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4952#ifdef SO_BINDTODEVICE
4953 if (!*args[cur_arg + 1]) {
4954 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004958 }
4959 if (curproxy->iface_name)
4960 free(curproxy->iface_name);
4961
4962 curproxy->iface_name = strdup(args[cur_arg + 1]);
4963 curproxy->iface_len = strlen(curproxy->iface_name);
4964 global.last_checks |= LSTCHK_NETADM;
4965#else
4966 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4967 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004970#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004971 cur_arg += 2;
4972 continue;
4973 }
4974 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004975 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004980 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4981 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4982 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4989 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993
4994 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004995 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004996 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 }
5000 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005002 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005003 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006 }
5007 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005009 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005010 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005011 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 }
5014 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005016 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005017 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005018 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
5021 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005023 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005024 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005028 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005030 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005031 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005033 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005034 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005035 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005037 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005038 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005040 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005041 }
5042 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005044 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005045 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056
5057 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005058 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005059 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
5063 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005065 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005066 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005072 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005073 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
5077 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005079 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005080 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005081 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
5084 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005086 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005087 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005091 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005093 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005094 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005096 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005099 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005100
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 if (curproxy == &defproxy) {
5102 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005106 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 if (*(args[1]) == 0) {
5110 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005114
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005115 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005116 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5117 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5118 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
5121 }
5122 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5123 }
5124 else if (*args[2]) {
5125 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5126 file, linenum, args[0], args[2]);
5127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005131 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005132 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005133 wl->s = strdup(args[1]);
5134 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005135 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005144
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005147 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005154 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
5158 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005161 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
5165 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005175 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
5179 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005181 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005182 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005183 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
5186 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005188 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005189 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
5193 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005194 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005195
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 if (curproxy == &defproxy) {
5197 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005201 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 if (*(args[1]) == 0) {
5205 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
5209
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005210 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005211 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5212 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5213 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217 err_code |= warnif_cond_requires_req(cond, file, linenum);
5218 }
5219 else if (*args[2]) {
5220 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5221 file, linenum, args[0], args[2]);
5222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005226 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005227 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005228 wl->s = strdup(args[1]);
5229 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "errorloc") ||
5232 !strcmp(args[0], "errorloc302") ||
5233 !strcmp(args[0], "errorloc303")) { /* error location */
5234 int errnum, errlen;
5235 char *err;
5236
Willy Tarreau977b8e42006-12-29 14:19:17 +01005237 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005238 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005239
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005241 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245
5246 errnum = atol(args[1]);
5247 if (!strcmp(args[0], "errorloc303")) {
5248 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5249 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5250 } else {
5251 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5252 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5253 }
5254
Willy Tarreau0f772532006-12-23 20:51:41 +01005255 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5256 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005257 chunk_destroy(&curproxy->errmsg[rc]);
5258 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005259 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005262
5263 if (rc >= HTTP_ERR_SIZE) {
5264 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5265 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 free(err);
5267 }
5268 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005269 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5270 int errnum, errlen, fd;
5271 char *err;
5272 struct stat stat;
5273
5274 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005276
5277 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005278 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005281 }
5282
5283 fd = open(args[2], O_RDONLY);
5284 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5285 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5286 file, linenum, args[2], args[1]);
5287 if (fd >= 0)
5288 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005291 }
5292
Willy Tarreau27a674e2009-08-17 07:23:33 +02005293 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005294 errlen = stat.st_size;
5295 } else {
5296 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005297 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005299 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005300 }
5301
5302 err = malloc(errlen); /* malloc() must succeed during parsing */
5303 errnum = read(fd, err, errlen);
5304 if (errnum != errlen) {
5305 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5306 file, linenum, args[2], args[1]);
5307 close(fd);
5308 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005311 }
5312 close(fd);
5313
5314 errnum = atol(args[1]);
5315 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5316 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005317 chunk_destroy(&curproxy->errmsg[rc]);
5318 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005319 break;
5320 }
5321 }
5322
5323 if (rc >= HTTP_ERR_SIZE) {
5324 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5325 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005327 free(err);
5328 }
5329 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005330 else if (!strcmp(args[0], "compression")) {
5331 struct comp *comp;
5332 if (curproxy->comp == NULL) {
5333 comp = calloc(1, sizeof(struct comp));
5334 curproxy->comp = comp;
5335 } else {
5336 comp = curproxy->comp;
5337 }
5338
5339 if (!strcmp(args[1], "algo")) {
5340 int cur_arg;
William Lallemand552df672012-11-07 13:21:47 +01005341 struct comp_ctx ctx;
5342
William Lallemand82fe75c2012-10-23 10:25:10 +02005343 cur_arg = 2;
5344 if (!*args[cur_arg]) {
5345 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5346 file, linenum, args[0]);
5347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
5349 }
5350 while (*(args[cur_arg])) {
5351 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5352 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5353 file, linenum, args[0], args[cur_arg]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
William Lallemand552df672012-11-07 13:21:47 +01005357 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5358 curproxy->comp->algos->end(&ctx);
5359 } else {
5360 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5361 file, linenum, args[0], args[cur_arg]);
5362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
5364 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005365 cur_arg ++;
5366 continue;
5367 }
5368 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005369 else if (!strcmp(args[1], "offload")) {
5370 comp->offload = 1;
5371 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005372 else if (!strcmp(args[1], "type")) {
5373 int cur_arg;
5374 cur_arg = 2;
5375 if (!*args[cur_arg]) {
5376 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5377 file, linenum, args[0]);
5378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
5380 }
5381 while (*(args[cur_arg])) {
5382 comp_append_type(comp, args[cur_arg]);
5383 cur_arg ++;
5384 continue;
5385 }
5386 }
5387 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005388 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005389 file, linenum, args[0]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005395 struct cfg_kw_list *kwl;
5396 int index;
5397
5398 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5399 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5400 if (kwl->kw[index].section != CFG_LISTEN)
5401 continue;
5402 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5403 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005404 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005405 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005406 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005409 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005410 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005411 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_WARN;
5413 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005414 }
Willy Tarreau93893792009-07-23 13:19:11 +02005415 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005416 }
5417 }
5418 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005419
Willy Tarreau6daf3432008-01-22 16:44:08 +01005420 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 }
Willy Tarreau93893792009-07-23 13:19:11 +02005424 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005425 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005426 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427}
5428
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005429int
5430cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5431{
5432
5433 int err_code = 0;
5434 const char *err;
5435
5436 if (!strcmp(args[0], "userlist")) { /* new userlist */
5437 struct userlist *newul;
5438
5439 if (!*args[1]) {
5440 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5441 file, linenum, args[0]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445
5446 err = invalid_char(args[1]);
5447 if (err) {
5448 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5449 file, linenum, *err, args[0], args[1]);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453
5454 for (newul = userlist; newul; newul = newul->next)
5455 if (!strcmp(newul->name, args[1])) {
5456 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5457 file, linenum, args[1]);
5458 err_code |= ERR_WARN;
5459 goto out;
5460 }
5461
5462 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5463 if (!newul) {
5464 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5465 err_code |= ERR_ALERT | ERR_ABORT;
5466 goto out;
5467 }
5468
5469 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5470 newul->name = strdup(args[1]);
5471
5472 if (!newul->groupusers | !newul->name) {
5473 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5474 err_code |= ERR_ALERT | ERR_ABORT;
5475 goto out;
5476 }
5477
5478 newul->next = userlist;
5479 userlist = newul;
5480
5481 } else if (!strcmp(args[0], "group")) { /* new group */
5482 int cur_arg, i;
5483 const char *err;
5484
5485 if (!*args[1]) {
5486 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5487 file, linenum, args[0]);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
5491
5492 err = invalid_char(args[1]);
5493 if (err) {
5494 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5495 file, linenum, *err, args[0], args[1]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499
5500 for(i = 0; i < userlist->grpcnt; i++)
5501 if (!strcmp(userlist->groups[i], args[1])) {
5502 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5503 file, linenum, args[1], userlist->name);
5504 err_code |= ERR_ALERT;
5505 goto out;
5506 }
5507
5508 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5509 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5510 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
5513 }
5514
5515 cur_arg = 2;
5516
5517 while (*args[cur_arg]) {
5518 if (!strcmp(args[cur_arg], "users")) {
5519 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5520 cur_arg += 2;
5521 continue;
5522 } else {
5523 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5524 file, linenum, args[0]);
5525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
5527 }
5528 }
5529
5530 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5531 } else if (!strcmp(args[0], "user")) { /* new user */
5532 struct auth_users *newuser;
5533 int cur_arg;
5534
5535 if (!*args[1]) {
5536 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5537 file, linenum, args[0]);
5538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
5540 }
5541
5542 for (newuser = userlist->users; newuser; newuser = newuser->next)
5543 if (!strcmp(newuser->user, args[1])) {
5544 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5545 file, linenum, args[1], userlist->name);
5546 err_code |= ERR_ALERT;
5547 goto out;
5548 }
5549
5550 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5551 if (!newuser) {
5552 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5553 err_code |= ERR_ALERT | ERR_ABORT;
5554 goto out;
5555 }
5556
5557 newuser->user = strdup(args[1]);
5558
5559 newuser->next = userlist->users;
5560 userlist->users = newuser;
5561
5562 cur_arg = 2;
5563
5564 while (*args[cur_arg]) {
5565 if (!strcmp(args[cur_arg], "password")) {
5566#ifndef CONFIG_HAP_CRYPT
5567 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5568 file, linenum);
5569 err_code |= ERR_ALERT;
5570#endif
5571 newuser->pass = strdup(args[cur_arg + 1]);
5572 cur_arg += 2;
5573 continue;
5574 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5575 newuser->pass = strdup(args[cur_arg + 1]);
5576 newuser->flags |= AU_O_INSECURE;
5577 cur_arg += 2;
5578 continue;
5579 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005580 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005581 cur_arg += 2;
5582 continue;
5583 } else {
5584 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5585 file, linenum, args[0]);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
5589 }
5590 } else {
5591 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5592 err_code |= ERR_ALERT | ERR_FATAL;
5593 }
5594
5595out:
5596 return err_code;
5597}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598
5599/*
5600 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005601 * Returns the error code, 0 if OK, or any combination of :
5602 * - ERR_ABORT: must abort ASAP
5603 * - ERR_FATAL: we can continue parsing but not start the service
5604 * - ERR_WARN: a warning has been emitted
5605 * - ERR_ALERT: an alert has been emitted
5606 * Only the two first ones can stop processing, the two others are just
5607 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005609int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005611 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 FILE *f;
5613 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005615 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 if ((f=fopen(file,"r")) == NULL)
5618 return -1;
5619
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005620 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005621 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005622 char *end;
5623 char *args[MAX_LINE_ARGS + 1];
5624 char *line = thisline;
5625
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 linenum++;
5627
5628 end = line + strlen(line);
5629
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005630 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5631 /* Check if we reached the limit and the last char is not \n.
5632 * Watch out for the last line without the terminating '\n'!
5633 */
5634 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005635 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005636 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005637 }
5638
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005640 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 line++;
5642
5643 arg = 0;
5644 args[arg] = line;
5645
5646 while (*line && arg < MAX_LINE_ARGS) {
5647 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5648 * C equivalent value. Other combinations left unchanged (eg: \1).
5649 */
5650 if (*line == '\\') {
5651 int skip = 0;
5652 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5653 *line = line[1];
5654 skip = 1;
5655 }
5656 else if (line[1] == 'r') {
5657 *line = '\r';
5658 skip = 1;
5659 }
5660 else if (line[1] == 'n') {
5661 *line = '\n';
5662 skip = 1;
5663 }
5664 else if (line[1] == 't') {
5665 *line = '\t';
5666 skip = 1;
5667 }
5668 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005669 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 unsigned char hex1, hex2;
5671 hex1 = toupper(line[2]) - '0';
5672 hex2 = toupper(line[3]) - '0';
5673 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5674 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5675 *line = (hex1<<4) + hex2;
5676 skip = 3;
5677 }
5678 else {
5679 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005680 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682 }
5683 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005684 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 end -= skip;
5686 }
5687 line++;
5688 }
5689 else if (*line == '#' || *line == '\n' || *line == '\r') {
5690 /* end of string, end of loop */
5691 *line = 0;
5692 break;
5693 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005694 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005696 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005697 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 line++;
5699 args[++arg] = line;
5700 }
5701 else {
5702 line++;
5703 }
5704 }
5705
5706 /* empty line */
5707 if (!**args)
5708 continue;
5709
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005710 if (*line) {
5711 /* we had to stop due to too many args.
5712 * Let's terminate the string, print the offending part then cut the
5713 * last arg.
5714 */
5715 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5716 line++;
5717 *line = '\0';
5718
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005719 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005720 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 args[arg] = line;
5723 }
5724
Willy Tarreau540abe42007-05-02 20:50:16 +02005725 /* zero out remaining args and ensure that at least one entry
5726 * is zeroed out.
5727 */
5728 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 args[arg] = line;
5730 }
5731
Willy Tarreau3842f002009-06-14 11:39:52 +02005732 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005733 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005734 char *tmp;
5735
Willy Tarreau3842f002009-06-14 11:39:52 +02005736 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005737 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005738 for (arg=0; *args[arg+1]; arg++)
5739 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005740 *tmp = '\0'; // fix the next arg to \0
5741 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005742 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005743 else if (!strcmp(args[0], "default")) {
5744 kwm = KWM_DEF;
5745 for (arg=0; *args[arg+1]; arg++)
5746 args[arg] = args[arg+1]; // shift args after inversion
5747 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005748
William Lallemand0f99e342011-10-12 17:50:54 +02005749 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5750 strcmp(args[0], "log") != 0) {
5751 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005752 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005753 }
5754
Willy Tarreau977b8e42006-12-29 14:19:17 +01005755 if (!strcmp(args[0], "listen") ||
5756 !strcmp(args[0], "frontend") ||
5757 !strcmp(args[0], "backend") ||
5758 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005759 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005761 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005762 cursection = strdup(args[0]);
5763 }
5764 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005766 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005767 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005768 }
5769 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005770 confsect = CFG_USERLIST;
5771 free(cursection);
5772 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005773 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005774 else if (!strcmp(args[0], "peers")) {
5775 confsect = CFG_PEERS;
5776 free(cursection);
5777 cursection = strdup(args[0]);
5778 }
5779
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 /* else it's a section keyword */
5781
5782 switch (confsect) {
5783 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005784 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 break;
5786 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005787 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005789 case CFG_USERLIST:
5790 err_code |= cfg_parse_users(file, linenum, args, kwm);
5791 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005792 case CFG_PEERS:
5793 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5794 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005796 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005799
5800 if (err_code & ERR_ABORT)
5801 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005803 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005804 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005806 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005807}
5808
Willy Tarreaubb925012009-07-23 13:36:36 +02005809/*
5810 * Returns the error code, 0 if OK, or any combination of :
5811 * - ERR_ABORT: must abort ASAP
5812 * - ERR_FATAL: we can continue parsing but not start the service
5813 * - ERR_WARN: a warning has been emitted
5814 * - ERR_ALERT: an alert has been emitted
5815 * Only the two first ones can stop processing, the two others are just
5816 * indicators.
5817 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005818int check_config_validity()
5819{
5820 int cfgerr = 0;
5821 struct proxy *curproxy = NULL;
5822 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005823 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005824 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005825 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005826 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005828 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 /*
5830 * Now, check for the integrity of all that we have collected.
5831 */
5832
5833 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005834 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005836 /* first, we will invert the proxy list order */
5837 curproxy = NULL;
5838 while (proxy) {
5839 struct proxy *next;
5840
5841 next = proxy->next;
5842 proxy->next = curproxy;
5843 curproxy = proxy;
5844 if (!next)
5845 break;
5846 proxy = next;
5847 }
5848
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005850 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005851 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005852 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005853 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005854 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005855 unsigned int next_id;
5856
Willy Tarreau050536d2012-10-04 08:47:34 +02005857 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005858 /* proxy ID not set, use automatic numbering with first
5859 * spare entry starting with next_pxid.
5860 */
5861 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5862 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5863 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005864 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005865 next_pxid++;
5866
Willy Tarreau55ea7572007-06-17 19:56:27 +02005867
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005869 /* ensure we don't keep listeners uselessly bound */
5870 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871 curproxy = curproxy->next;
5872 continue;
5873 }
5874
Willy Tarreauff01a212009-03-15 13:46:16 +01005875 switch (curproxy->mode) {
5876 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005877 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005878 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5880 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005881 cfgerr++;
5882 }
5883
5884 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005885 Warning("config : servers will be ignored for %s '%s'.\n",
5886 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005887 break;
5888
5889 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005890 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005891 break;
5892
5893 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005894 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005895 break;
5896 }
5897
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005898 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005899 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005900 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005901 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5902 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005903 cfgerr++;
5904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005906 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005907 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5908 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005909 cfgerr++;
5910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005912 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005913 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5914 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005915 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005916 }
5917 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005918 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005919 /* If no LB algo is set in a backend, and we're not in
5920 * transparent mode, dispatch mode nor proxy mode, we
5921 * want to use balance roundrobin by default.
5922 */
5923 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5924 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 }
5926 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005927
Willy Tarreau1620ec32011-08-06 17:05:02 +02005928 if (curproxy->options & PR_O_DISPATCH)
5929 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5930 else if (curproxy->options & PR_O_HTTP_PROXY)
5931 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5932 else if (curproxy->options & PR_O_TRANSP)
5933 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005934
Willy Tarreau1620ec32011-08-06 17:05:02 +02005935 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5936 if (curproxy->options & PR_O_DISABLE404) {
5937 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5938 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5939 err_code |= ERR_WARN;
5940 curproxy->options &= ~PR_O_DISABLE404;
5941 }
5942 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5943 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5944 "send-state", proxy_type_str(curproxy), curproxy->id);
5945 err_code |= ERR_WARN;
5946 curproxy->options &= ~PR_O2_CHK_SNDST;
5947 }
Willy Tarreauef781042010-01-27 11:53:01 +01005948 }
5949
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005950 /* if a default backend was specified, let's find it */
5951 if (curproxy->defbe.name) {
5952 struct proxy *target;
5953
Alex Williams96532db2009-11-01 21:27:13 -05005954 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005955 if (!target) {
5956 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5957 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005958 cfgerr++;
5959 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005960 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5961 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005962 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005963 } else {
5964 free(curproxy->defbe.name);
5965 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005966 /* we force the backend to be present on at least all of
5967 * the frontend's processes.
5968 */
5969 target->bind_proc = curproxy->bind_proc ?
5970 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005971
5972 /* Emit a warning if this proxy also has some servers */
5973 if (curproxy->srv) {
5974 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5975 curproxy->id);
5976 err_code |= ERR_WARN;
5977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 }
5979 }
5980
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005981 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005982 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5983 /* map jump target for ACT_SETBE in req_rep chain */
5984 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005985 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005986 struct proxy *target;
5987
Willy Tarreaua496b602006-12-17 23:15:24 +01005988 if (exp->action != ACT_SETBE)
5989 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005990
Alex Williams96532db2009-11-01 21:27:13 -05005991 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005992 if (!target) {
5993 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5994 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005995 cfgerr++;
5996 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005997 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5998 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005999 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006000 } else {
6001 free((void *)exp->replace);
6002 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006003 /* we force the backend to be present on at least all of
6004 * the frontend's processes.
6005 */
6006 target->bind_proc = curproxy->bind_proc ?
6007 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006008 }
6009 }
6010 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006011
6012 /* find the target proxy for 'use_backend' rules */
6013 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006014 struct proxy *target;
6015
Alex Williams96532db2009-11-01 21:27:13 -05006016 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006017
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006018 if (!target) {
6019 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6020 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006021 cfgerr++;
6022 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006023 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6024 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006025 cfgerr++;
6026 } else {
6027 free((void *)rule->be.name);
6028 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006029 /* we force the backend to be present on at least all of
6030 * the frontend's processes.
6031 */
6032 target->bind_proc = curproxy->bind_proc ?
6033 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006034 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006035 }
6036
6037 /* find the target proxy for 'use_backend' rules */
6038 list_for_each_entry(srule, &curproxy->server_rules, list) {
6039 struct server *target = findserver(curproxy, srule->srv.name);
6040
6041 if (!target) {
6042 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6043 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6044 cfgerr++;
6045 continue;
6046 }
6047 free((void *)srule->srv.name);
6048 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006049 }
6050
Emeric Brunb982a3d2010-01-04 15:45:53 +01006051 /* find the target table for 'stick' rules */
6052 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6053 struct proxy *target;
6054
Emeric Brun1d33b292010-01-04 15:47:17 +01006055 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6056 if (mrule->flags & STK_IS_STORE)
6057 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6058
Emeric Brunb982a3d2010-01-04 15:45:53 +01006059 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006060 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006061 else
6062 target = curproxy;
6063
6064 if (!target) {
6065 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6066 curproxy->id, mrule->table.name);
6067 cfgerr++;
6068 }
6069 else if (target->table.size == 0) {
6070 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6071 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6072 cfgerr++;
6073 }
Willy Tarreau12785782012-04-27 21:37:17 +02006074 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6075 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006076 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6077 cfgerr++;
6078 }
6079 else {
6080 free((void *)mrule->table.name);
6081 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006082 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006083 }
6084 }
6085
6086 /* find the target table for 'store response' rules */
6087 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6088 struct proxy *target;
6089
Emeric Brun1d33b292010-01-04 15:47:17 +01006090 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6091
Emeric Brunb982a3d2010-01-04 15:45:53 +01006092 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006093 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006094 else
6095 target = curproxy;
6096
6097 if (!target) {
6098 Alert("Proxy '%s': unable to find store table '%s'.\n",
6099 curproxy->id, mrule->table.name);
6100 cfgerr++;
6101 }
6102 else if (target->table.size == 0) {
6103 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6104 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6105 cfgerr++;
6106 }
Willy Tarreau12785782012-04-27 21:37:17 +02006107 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6108 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006109 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6110 cfgerr++;
6111 }
6112 else {
6113 free((void *)mrule->table.name);
6114 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006115 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006116 }
6117 }
6118
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006119 /* find the target table for 'tcp-request' layer 4 rules */
6120 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6121 struct proxy *target;
6122
Willy Tarreau56123282010-08-06 19:06:56 +02006123 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006124 continue;
6125
6126 if (trule->act_prm.trk_ctr.table.n)
6127 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6128 else
6129 target = curproxy;
6130
6131 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006132 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6133 curproxy->id, trule->act_prm.trk_ctr.table.n,
6134 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006135 cfgerr++;
6136 }
6137 else if (target->table.size == 0) {
6138 Alert("Proxy '%s': table '%s' used but not configured.\n",
6139 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6140 cfgerr++;
6141 }
6142 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006143 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006144 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6145 cfgerr++;
6146 }
6147 else {
6148 free(trule->act_prm.trk_ctr.table.n);
6149 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006150 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006151 * to pass a list of counters to track and allocate them right here using
6152 * stktable_alloc_data_type().
6153 */
6154 }
6155 }
6156
Willy Tarreaud1f96522010-08-03 19:34:32 +02006157 /* find the target table for 'tcp-request' layer 6 rules */
6158 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6159 struct proxy *target;
6160
Willy Tarreau56123282010-08-06 19:06:56 +02006161 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006162 continue;
6163
6164 if (trule->act_prm.trk_ctr.table.n)
6165 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6166 else
6167 target = curproxy;
6168
6169 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006170 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6171 curproxy->id, trule->act_prm.trk_ctr.table.n,
6172 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006173 cfgerr++;
6174 }
6175 else if (target->table.size == 0) {
6176 Alert("Proxy '%s': table '%s' used but not configured.\n",
6177 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6178 cfgerr++;
6179 }
6180 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006181 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006182 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6183 cfgerr++;
6184 }
6185 else {
6186 free(trule->act_prm.trk_ctr.table.n);
6187 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006188 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006189 * to pass a list of counters to track and allocate them right here using
6190 * stktable_alloc_data_type().
6191 */
6192 }
6193 }
6194
Emeric Brun32da3c42010-09-23 18:39:19 +02006195 if (curproxy->table.peers.name) {
6196 struct peers *curpeers = peers;
6197
6198 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6199 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6200 free((void *)curproxy->table.peers.name);
6201 curproxy->table.peers.p = peers;
6202 break;
6203 }
6204 }
6205
6206 if (!curpeers) {
6207 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6208 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006209 free((void *)curproxy->table.peers.name);
6210 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006211 cfgerr++;
6212 }
6213 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006214 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6215 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006216 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006217 cfgerr++;
6218 }
6219 }
6220
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006221 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006222 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006223 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6224 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6225 "proxy", curproxy->id);
6226 cfgerr++;
6227 goto out_uri_auth_compat;
6228 }
6229
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006230 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006231 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006232 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006233 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006234
Willy Tarreau95fa4692010-02-01 13:05:50 +01006235 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6236 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006237
6238 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006239 uri_auth_compat_req[i++] = "realm";
6240 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6241 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006242
Willy Tarreau95fa4692010-02-01 13:05:50 +01006243 uri_auth_compat_req[i++] = "unless";
6244 uri_auth_compat_req[i++] = "{";
6245 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6246 uri_auth_compat_req[i++] = "}";
6247 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006248
Willy Tarreauff011f22011-01-06 17:51:27 +01006249 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6250 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006251 cfgerr++;
6252 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006253 }
6254
Willy Tarreauff011f22011-01-06 17:51:27 +01006255 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006256
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006257 if (curproxy->uri_auth->auth_realm) {
6258 free(curproxy->uri_auth->auth_realm);
6259 curproxy->uri_auth->auth_realm = NULL;
6260 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006261
6262 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006263 }
6264out_uri_auth_compat:
6265
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006266 cfgerr += acl_find_targets(curproxy);
6267
Willy Tarreau2738a142006-07-08 17:28:09 +02006268 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006269 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006270 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006271 (!curproxy->timeout.connect ||
6272 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006273 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006274 " | While not properly invalid, you will certainly encounter various problems\n"
6275 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006276 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006277 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006278 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006279 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006280
Willy Tarreau1fa31262007-12-03 00:36:16 +01006281 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6282 * We must still support older configurations, so let's find out whether those
6283 * parameters have been set or must be copied from contimeouts.
6284 */
6285 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006286 if (!curproxy->timeout.tarpit ||
6287 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006288 /* tarpit timeout not set. We search in the following order:
6289 * default.tarpit, curr.connect, default.connect.
6290 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006291 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006292 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006293 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006294 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006295 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006296 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006297 }
6298 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006299 (!curproxy->timeout.queue ||
6300 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006301 /* queue timeout not set. We search in the following order:
6302 * default.queue, curr.connect, default.connect.
6303 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006304 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006305 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006306 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006307 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006308 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006309 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006310 }
6311 }
6312
Willy Tarreau1620ec32011-08-06 17:05:02 +02006313 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006314 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6315 curproxy->check_req = (char *)malloc(curproxy->check_len);
6316 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006317 }
6318
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006319 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006320 if (curproxy->nb_req_cap) {
6321 if (curproxy->mode == PR_MODE_HTTP) {
6322 curproxy->req_cap_pool = create_pool("ptrcap",
6323 curproxy->nb_req_cap * sizeof(char *),
6324 MEM_F_SHARED);
6325 } else {
6326 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6327 proxy_type_str(curproxy), curproxy->id);
6328 err_code |= ERR_WARN;
6329 curproxy->to_log &= ~LW_REQHDR;
6330 curproxy->nb_req_cap = 0;
6331 }
6332 }
6333
6334 if (curproxy->nb_rsp_cap) {
6335 if (curproxy->mode == PR_MODE_HTTP) {
6336 curproxy->rsp_cap_pool = create_pool("ptrcap",
6337 curproxy->nb_rsp_cap * sizeof(char *),
6338 MEM_F_SHARED);
6339 } else {
6340 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6341 proxy_type_str(curproxy), curproxy->id);
6342 err_code |= ERR_WARN;
6343 curproxy->to_log &= ~LW_REQHDR;
6344 curproxy->nb_rsp_cap = 0;
6345 }
6346 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006347
Willy Tarreau196729e2012-05-31 19:30:26 +02006348 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006349 if (!(curproxy->cap & PR_CAP_FE)) {
6350 if (curproxy->logformat_string != default_http_log_format &&
6351 curproxy->logformat_string != default_tcp_log_format &&
6352 curproxy->logformat_string != clf_http_log_format)
6353 free(curproxy->logformat_string);
6354 curproxy->logformat_string = NULL;
6355 }
6356
Willy Tarreau196729e2012-05-31 19:30:26 +02006357 if (curproxy->logformat_string)
6358 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6359
6360 if (curproxy->uniqueid_format_string)
6361 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6362
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 /* first, we will invert the servers list order */
6364 newsrv = NULL;
6365 while (curproxy->srv) {
6366 struct server *next;
6367
6368 next = curproxy->srv->next;
6369 curproxy->srv->next = newsrv;
6370 newsrv = curproxy->srv;
6371 if (!next)
6372 break;
6373 curproxy->srv = next;
6374 }
6375
Willy Tarreaudd701652010-05-25 23:03:02 +02006376 /* assign automatic UIDs to servers which don't have one yet */
6377 next_id = 1;
6378 newsrv = curproxy->srv;
6379 while (newsrv != NULL) {
6380 if (!newsrv->puid) {
6381 /* server ID not set, use automatic numbering with first
6382 * spare entry starting with next_svid.
6383 */
6384 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6385 newsrv->conf.id.key = newsrv->puid = next_id;
6386 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6387 }
6388 next_id++;
6389 newsrv = newsrv->next;
6390 }
6391
Willy Tarreau20697042007-11-15 23:26:18 +01006392 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006393 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394
Willy Tarreau62c3be22012-01-20 13:12:32 +01006395 /*
6396 * If this server supports a maxconn parameter, it needs a dedicated
6397 * tasks to fill the emptied slots when a connection leaves.
6398 * Also, resolve deferred tracking dependency if needed.
6399 */
6400 newsrv = curproxy->srv;
6401 while (newsrv != NULL) {
6402 if (newsrv->minconn > newsrv->maxconn) {
6403 /* Only 'minconn' was specified, or it was higher than or equal
6404 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6405 * this will avoid further useless expensive computations.
6406 */
6407 newsrv->maxconn = newsrv->minconn;
6408 } else if (newsrv->maxconn && !newsrv->minconn) {
6409 /* minconn was not specified, so we set it to maxconn */
6410 newsrv->minconn = newsrv->maxconn;
6411 }
6412
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006413#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006414 if (newsrv->use_ssl || newsrv->check.use_ssl)
6415 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006416#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006417
Willy Tarreau62c3be22012-01-20 13:12:32 +01006418 if (newsrv->trackit) {
6419 struct proxy *px;
6420 struct server *srv;
6421 char *pname, *sname;
6422
6423 pname = newsrv->trackit;
6424 sname = strrchr(pname, '/');
6425
6426 if (sname)
6427 *sname++ = '\0';
6428 else {
6429 sname = pname;
6430 pname = NULL;
6431 }
6432
6433 if (pname) {
6434 px = findproxy(pname, PR_CAP_BE);
6435 if (!px) {
6436 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6437 proxy_type_str(curproxy), curproxy->id,
6438 newsrv->id, pname);
6439 cfgerr++;
6440 goto next_srv;
6441 }
6442 } else
6443 px = curproxy;
6444
6445 srv = findserver(px, sname);
6446 if (!srv) {
6447 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6448 proxy_type_str(curproxy), curproxy->id,
6449 newsrv->id, sname);
6450 cfgerr++;
6451 goto next_srv;
6452 }
6453
6454 if (!(srv->state & SRV_CHECKED)) {
6455 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6456 "tracking as it does not have checks enabled.\n",
6457 proxy_type_str(curproxy), curproxy->id,
6458 newsrv->id, px->id, srv->id);
6459 cfgerr++;
6460 goto next_srv;
6461 }
6462
6463 if (curproxy != px &&
6464 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6465 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6466 "tracking: disable-on-404 option inconsistency.\n",
6467 proxy_type_str(curproxy), curproxy->id,
6468 newsrv->id, px->id, srv->id);
6469 cfgerr++;
6470 goto next_srv;
6471 }
6472
6473 /* if the other server is forced disabled, we have to do the same here */
6474 if (srv->state & SRV_MAINTAIN) {
6475 newsrv->state |= SRV_MAINTAIN;
6476 newsrv->state &= ~SRV_RUNNING;
6477 newsrv->health = 0;
6478 }
6479
6480 newsrv->track = srv;
6481 newsrv->tracknext = srv->tracknext;
6482 srv->tracknext = newsrv;
6483
6484 free(newsrv->trackit);
6485 newsrv->trackit = NULL;
6486 }
6487 next_srv:
6488 newsrv = newsrv->next;
6489 }
6490
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006491 /* We have to initialize the server lookup mechanism depending
6492 * on what LB algorithm was choosen.
6493 */
6494
6495 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6496 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6497 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006498 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6499 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6500 init_server_map(curproxy);
6501 } else {
6502 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6503 fwrr_init_server_groups(curproxy);
6504 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006505 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006506
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006507 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006508 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6509 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6510 fwlc_init_server_tree(curproxy);
6511 } else {
6512 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6513 fas_init_server_tree(curproxy);
6514 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006515 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006516
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006517 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006518 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6519 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6520 chash_init_server_tree(curproxy);
6521 } else {
6522 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6523 init_server_map(curproxy);
6524 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006525 break;
6526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527
6528 if (curproxy->options & PR_O_LOGASAP)
6529 curproxy->to_log &= ~LW_BYTES;
6530
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006531 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006532 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006533 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6534 proxy_type_str(curproxy), curproxy->id);
6535 err_code |= ERR_WARN;
6536 }
6537
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006538 if (curproxy->mode != PR_MODE_HTTP) {
6539 int optnum;
6540
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006541 if (curproxy->uri_auth) {
6542 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6543 proxy_type_str(curproxy), curproxy->id);
6544 err_code |= ERR_WARN;
6545 curproxy->uri_auth = NULL;
6546 }
6547
Willy Tarreau87cf5142011-08-19 22:57:24 +02006548 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006549 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6550 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6551 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006552 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006553 }
6554
6555 if (curproxy->options & PR_O_ORGTO) {
6556 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6557 "originalto", proxy_type_str(curproxy), curproxy->id);
6558 err_code |= ERR_WARN;
6559 curproxy->options &= ~PR_O_ORGTO;
6560 }
6561
6562 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6563 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6564 (curproxy->cap & cfg_opts[optnum].cap) &&
6565 (curproxy->options & cfg_opts[optnum].val)) {
6566 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6567 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6568 err_code |= ERR_WARN;
6569 curproxy->options &= ~cfg_opts[optnum].val;
6570 }
6571 }
6572
6573 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6574 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6575 (curproxy->cap & cfg_opts2[optnum].cap) &&
6576 (curproxy->options2 & cfg_opts2[optnum].val)) {
6577 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6578 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6579 err_code |= ERR_WARN;
6580 curproxy->options2 &= ~cfg_opts2[optnum].val;
6581 }
6582 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006583
Willy Tarreauefa5f512010-03-30 20:13:29 +02006584#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006585 if (curproxy->bind_hdr_occ) {
6586 curproxy->bind_hdr_occ = 0;
6587 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6588 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6589 err_code |= ERR_WARN;
6590 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006591#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006592 }
6593
Willy Tarreaubaaee002006-06-26 02:48:02 +02006594 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006595 * ensure that we're not cross-dressing a TCP server into HTTP.
6596 */
6597 newsrv = curproxy->srv;
6598 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006599 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006600 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6601 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006602 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006603 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006604
Willy Tarreau0cec3312011-10-31 13:49:26 +01006605 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6606 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6607 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6608 err_code |= ERR_WARN;
6609 }
6610
Willy Tarreauefa5f512010-03-30 20:13:29 +02006611#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006612 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6613 newsrv->bind_hdr_occ = 0;
6614 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6615 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6616 err_code |= ERR_WARN;
6617 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006618#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006619 newsrv = newsrv->next;
6620 }
6621
Willy Tarreauc1a21672009-08-16 22:37:44 +02006622 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006623 if (!curproxy->accept)
6624 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006625
Willy Tarreauc1a21672009-08-16 22:37:44 +02006626 if (curproxy->tcp_req.inspect_delay ||
6627 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006628 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006629
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006630 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006631 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006632 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006633 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006634
6635 /* both TCP and HTTP must check switching rules */
6636 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6637 }
6638
6639 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006640 if (curproxy->tcp_req.inspect_delay ||
6641 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6642 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6643
Emeric Brun97679e72010-09-23 17:56:44 +02006644 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6645 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6646
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006647 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006648 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006649 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006650 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006651
6652 /* If the backend does requires RDP cookie persistence, we have to
6653 * enable the corresponding analyser.
6654 */
6655 if (curproxy->options2 & PR_O2_RDPC_PRST)
6656 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6657 }
6658
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006659 /* Configure SSL for each bind line.
6660 * Note: if configuration fails at some point, the ->ctx member
6661 * remains NULL so that listeners can later detach.
6662 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006663 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6664 if (!bind_conf->is_ssl)
6665 continue;
6666#ifdef USE_OPENSSL
6667 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006668 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006669 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006670 cfgerr++;
6671 continue;
6672 }
6673
Emeric Brun4b3091e2012-09-24 15:48:52 +02006674 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006675 Alert("Unable to allocate SSL session cache.\n");
6676 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006677 continue;
6678 }
6679
Emeric Brunfc0421f2012-09-07 17:30:07 +02006680 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006681 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006682#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006683 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006684
Willy Tarreaue6b98942007-10-29 01:09:36 +01006685 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006686 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006687 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006688 if (!listener->luid) {
6689 /* listener ID not set, use automatic numbering with first
6690 * spare entry starting with next_luid.
6691 */
6692 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6693 listener->conf.id.key = listener->luid = next_id;
6694 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006695 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006696 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006697
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006698 /* enable separate counters */
6699 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6700 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006701 if (!listener->name)
6702 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006703 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006704
Willy Tarreaue6b98942007-10-29 01:09:36 +01006705 if (curproxy->options & PR_O_TCP_NOLING)
6706 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006707 if (!listener->maxconn)
6708 listener->maxconn = curproxy->maxconn;
6709 if (!listener->backlog)
6710 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006711 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006712 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006713 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006714 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006715
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006716 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6717 listener->options |= LI_O_TCP_RULES;
6718
Willy Tarreaude3041d2010-05-31 10:56:17 +02006719 if (curproxy->mon_mask.s_addr)
6720 listener->options |= LI_O_CHK_MONNET;
6721
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006722 /* smart accept mode is automatic in HTTP mode */
6723 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006724 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006725 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6726 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006727 }
6728
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006729 /* Release unused SSL configs */
6730 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6731 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006732 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006733#ifdef USE_OPENSSL
6734 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006735 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006736 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006737 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006738 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006739#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006740 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006741
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006742 /* Check multi-process mode compatibility for the current proxy */
6743 if (global.nbproc > 1) {
6744 int nbproc = 0;
6745 if (curproxy->bind_proc) {
6746 int proc;
6747 for (proc = 0; proc < global.nbproc; proc++) {
6748 if (curproxy->bind_proc & (1 << proc)) {
6749 nbproc++;
6750 }
6751 }
6752 } else {
6753 nbproc = global.nbproc;
6754 }
6755 if (curproxy->table.peers.name) {
6756 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6757 curproxy->id);
6758 cfgerr++;
6759 }
6760 if (nbproc > 1) {
6761 if (curproxy->uri_auth) {
6762 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6763 curproxy->id);
6764 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6765 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6766 curproxy->id);
6767 }
6768 }
6769 if (curproxy->appsession_name) {
6770 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6771 curproxy->id);
6772 }
6773 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6774 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6775 curproxy->id);
6776 }
6777 }
6778 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006779
6780 /* create the task associated with the proxy */
6781 curproxy->task = task_new();
6782 if (curproxy->task) {
6783 curproxy->task->context = curproxy;
6784 curproxy->task->process = manage_proxy;
6785 /* no need to queue, it will be done automatically if some
6786 * listener gets limited.
6787 */
6788 curproxy->task->expire = TICK_ETERNITY;
6789 } else {
6790 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6791 curproxy->id);
6792 cfgerr++;
6793 }
6794
Willy Tarreaubaaee002006-06-26 02:48:02 +02006795 curproxy = curproxy->next;
6796 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006797
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006798 /* Check multi-process mode compatibility */
6799 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006800 if (global.stats_fe && !global.stats_fe->bind_proc) {
6801 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 +01006802 }
6803 }
6804
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6806 struct auth_users *curuser;
6807 int g;
6808
6809 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6810 unsigned int group_mask = 0;
6811 char *group = NULL;
6812
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006813 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814 continue;
6815
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006816 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006817
6818 for (g = 0; g < curuserlist->grpcnt; g++)
6819 if (!strcmp(curuserlist->groups[g], group))
6820 break;
6821
6822 if (g == curuserlist->grpcnt) {
6823 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6824 curuserlist->name, group, curuser->user);
6825 err_code |= ERR_ALERT | ERR_FATAL;
6826 goto out;
6827 }
6828
6829 group_mask |= (1 << g);
6830 }
6831
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006832 free(curuser->u.groups);
6833 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 }
6835
6836 for (g = 0; g < curuserlist->grpcnt; g++) {
6837 char *user = NULL;
6838
6839 if (!curuserlist->groupusers[g])
6840 continue;
6841
6842 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6843 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6844 if (!strcmp(curuser->user, user))
6845 break;
6846
6847 if (!curuser) {
6848 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6849 curuserlist->name, user, curuserlist->groups[g]);
6850 err_code |= ERR_ALERT | ERR_FATAL;
6851 goto out;
6852 }
6853
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006854 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006855 }
6856
6857 free(curuserlist->groupusers[g]);
6858 }
6859
6860 free(curuserlist->groupusers);
6861
6862#ifdef DEBUG_AUTH
6863 for (g = 0; g < curuserlist->grpcnt; g++) {
6864 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6865
6866 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006867 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006868 fprintf(stderr, " %s", curuser->user);
6869 }
6870
6871 fprintf(stderr, "\n");
6872 }
6873#endif
6874
Willy Tarreaufbb78422011-06-05 15:38:35 +02006875 }
6876
6877 /* automatically compute fullconn if not set. We must not do it in the
6878 * loop above because cross-references are not yet fully resolved.
6879 */
6880 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6881 /* If <fullconn> is not set, let's set it to 10% of the sum of
6882 * the possible incoming frontend's maxconns.
6883 */
6884 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6885 struct proxy *fe;
6886 int total = 0;
6887
6888 /* sum up the number of maxconns of frontends which
6889 * reference this backend at least once or which are
6890 * the same one ('listen').
6891 */
6892 for (fe = proxy; fe; fe = fe->next) {
6893 struct switching_rule *rule;
6894 struct hdr_exp *exp;
6895 int found = 0;
6896
6897 if (!(fe->cap & PR_CAP_FE))
6898 continue;
6899
6900 if (fe == curproxy) /* we're on a "listen" instance */
6901 found = 1;
6902
6903 if (fe->defbe.be == curproxy) /* "default_backend" */
6904 found = 1;
6905
6906 /* check if a "use_backend" rule matches */
6907 if (!found) {
6908 list_for_each_entry(rule, &fe->switching_rules, list) {
6909 if (rule->be.backend == curproxy) {
6910 found = 1;
6911 break;
6912 }
6913 }
6914 }
6915
6916 /* check if a "reqsetbe" rule matches */
6917 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6918 if (exp->action == ACT_SETBE &&
6919 (struct proxy *)exp->replace == curproxy) {
6920 found = 1;
6921 break;
6922 }
6923 }
6924
6925 /* now we've checked all possible ways to reference a backend
6926 * from a frontend.
6927 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006928 if (!found)
6929 continue;
6930 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006931 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006932 /* we have the sum of the maxconns in <total>. We only
6933 * keep 10% of that sum to set the default fullconn, with
6934 * a hard minimum of 1 (to avoid a divide by zero).
6935 */
6936 curproxy->fullconn = (total + 9) / 10;
6937 if (!curproxy->fullconn)
6938 curproxy->fullconn = 1;
6939 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006940 }
6941
Willy Tarreau056f5682010-06-06 15:51:11 +02006942 /* initialize stick-tables on backend capable proxies. This must not
6943 * be done earlier because the data size may be discovered while parsing
6944 * other proxies.
6945 */
6946 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006947 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006948
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006949 /*
6950 * Recount currently required checks.
6951 */
6952
6953 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6954 int optnum;
6955
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006956 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6957 if (curproxy->options & cfg_opts[optnum].val)
6958 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006959
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006960 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6961 if (curproxy->options2 & cfg_opts2[optnum].val)
6962 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006963 }
6964
Willy Tarreau122541c2011-09-07 21:24:49 +02006965 if (peers) {
6966 struct peers *curpeers = peers, **last;
6967 struct peer *p, *pb;
6968
6969 /* Remove all peers sections which don't have a valid listener.
6970 * This can happen when a peers section is never referenced and
6971 * does not contain a local peer.
6972 */
6973 last = &peers;
6974 while (*last) {
6975 curpeers = *last;
6976 if (curpeers->peers_fe) {
6977 last = &curpeers->next;
6978 continue;
6979 }
6980
6981 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6982 curpeers->id, localpeer);
6983
6984 p = curpeers->remote;
6985 while (p) {
6986 pb = p->next;
6987 free(p->id);
6988 free(p);
6989 p = pb;
6990 }
6991
6992 /* Destroy and unlink this curpeers section.
6993 * Note: curpeers is backed up into *last.
6994 */
6995 free(curpeers->id);
6996 curpeers = curpeers->next;
6997 free(*last);
6998 *last = curpeers;
6999 }
7000 }
7001
Willy Tarreauac1932d2011-10-24 19:14:41 +02007002 if (!global.tune.max_http_hdr)
7003 global.tune.max_http_hdr = MAX_HTTP_HDR;
7004
Willy Tarreau34eb6712011-10-24 18:15:04 +02007005 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007006 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007007 MEM_F_SHARED);
7008
Willy Tarreaubb925012009-07-23 13:36:36 +02007009 if (cfgerr > 0)
7010 err_code |= ERR_ALERT | ERR_FATAL;
7011 out:
7012 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007013}
7014
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007015/*
7016 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7017 * parsing sessions.
7018 */
7019void cfg_register_keywords(struct cfg_kw_list *kwl)
7020{
7021 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7022}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007023
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007024/*
7025 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7026 */
7027void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7028{
7029 LIST_DEL(&kwl->list);
7030 LIST_INIT(&kwl->list);
7031}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007032
7033/*
7034 * Local variables:
7035 * c-indent-level: 8
7036 * c-basic-offset: 8
7037 * End:
7038 */