blob: a57f1bf9a056480b5aff29fd6b75862c37bec6ea [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 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 Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' 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 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' 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 block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 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 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 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 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 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);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
730 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
731 break;
732 }
733
734 if (!i || args[1][i]) {
735 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
736 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
737 file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741
742 if (global.node)
743 free(global.node);
744
745 global.node = strdup(args[1]);
746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 else if (!strcmp(args[0], "pidfile")) {
748 if (global.pidfile != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.pidfile = strdup(args[1]);
759 }
760 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200762 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763
764 if (*(args[1]) == 0 || *(args[2]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769
770 facility = get_log_facility(args[2]);
771 if (facility < 0) {
772 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776
777 level = 7; /* max syslog level = debug */
778 if (*(args[3])) {
779 level = get_log_level(args[3]);
780 if (level < 0) {
781 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 }
786
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200787 minlvl = 0; /* limit syslog level to this level (emerg) */
788 if (*(args[4])) {
789 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200794 }
795 }
796
Robert Tsai81ae1952007-12-05 10:47:29 +0100797 if (args[1][0] == '/') {
798 logsrv.u.addr.sa_family = AF_UNIX;
799 logsrv.u.un = *str2sun(args[1]);
800 } else {
801 logsrv.u.addr.sa_family = AF_INET;
802 logsrv.u.in = *str2sa(args[1]);
803 if (!logsrv.u.in.sin_port)
804 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806
807 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 global.logfac1 = facility;
810 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200811 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100814 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 global.logfac2 = facility;
816 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200817 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 else {
820 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200823 }
824 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
825 if (global.spread_checks != 0) {
826 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200827 err_code |= ERR_ALERT;
828 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200829 }
830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200834 }
835 global.spread_checks = atol(args[1]);
836 if (global.spread_checks < 0 || global.spread_checks > 50) {
837 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200842 struct cfg_kw_list *kwl;
843 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200844 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200845
846 list_for_each_entry(kwl, &cfg_keywords.list, list) {
847 for (index = 0; kwl->kw[index].kw != NULL; index++) {
848 if (kwl->kw[index].section != CFG_GLOBAL)
849 continue;
850 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
851 /* prepare error message just in case */
852 snprintf(trash, sizeof(trash),
853 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200854 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
855 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200858 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200859 else if (rc > 0) {
860 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200861 err_code |= ERR_WARN;
862 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200863 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200865 }
866 }
867 }
868
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200872
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 out:
874 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875}
876
Willy Tarreau97cb7802010-01-03 20:23:58 +0100877/* Perform the most basic initialization of a proxy :
878 * memset(), list_init(*), reset_timeouts(*).
879 */
880static void init_new_proxy(struct proxy *p)
881{
882 memset(p, 0, sizeof(struct proxy));
883 LIST_INIT(&p->pendconns);
884 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100885 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100886 LIST_INIT(&p->block_cond);
887 LIST_INIT(&p->redirect_rules);
888 LIST_INIT(&p->mon_fail_cond);
889 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100890 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100891 LIST_INIT(&p->sticking_rules);
892 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100893 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100894 LIST_INIT(&p->req_add);
895 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100896
897 /* Timeouts are defined as -1 */
898 proxy_reset_timeouts(p);
899}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200901void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 defproxy.mode = PR_MODE_TCP;
905 defproxy.state = PR_STNEW;
906 defproxy.maxconn = cfg_maxpconn;
907 defproxy.conn_retries = CONN_RETRIES;
908 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100909
910 defproxy.defsrv.inter = DEF_CHKINTR;
911 defproxy.defsrv.fastinter = 0;
912 defproxy.defsrv.downinter = 0;
913 defproxy.defsrv.rise = DEF_RISETIME;
914 defproxy.defsrv.fall = DEF_FALLTIME;
915 defproxy.defsrv.check_port = 0;
916 defproxy.defsrv.maxqueue = 0;
917 defproxy.defsrv.minconn = 0;
918 defproxy.defsrv.maxconn = 0;
919 defproxy.defsrv.slowstart = 0;
920 defproxy.defsrv.onerror = DEF_HANA_ONERR;
921 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
922 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923}
924
Willy Tarreauade5ec42010-01-28 19:33:49 +0100925
926static int create_cond_regex_rule(const char *file, int line,
927 struct proxy *px, int dir, int action, int flags,
928 const char *cmd, const char *reg, const char *repl,
929 const char **cond_start)
930{
931 regex_t *preg = NULL;
932 const char *err;
933 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100934 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100935
936 if (px == &defproxy) {
937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto err;
940 }
941
942 if (*reg == 0) {
943 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto err;
946 }
947
948 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
949 err_code |= ERR_WARN;
950
Willy Tarreau5321c422010-01-28 20:35:13 +0100951 if (cond_start &&
952 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
953 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
954 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
955 file, line, cmd);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto err;
958 }
959 }
960 else if (cond_start && **cond_start) {
961 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
962 file, line, cmd, *cond_start);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto err;
965 }
966
967 if (dir == ACL_DIR_REQ)
968 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100969 else
970 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100971
Willy Tarreauade5ec42010-01-28 19:33:49 +0100972 preg = calloc(1, sizeof(regex_t));
973 if (!preg) {
974 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
975 err_code = ERR_ALERT | ERR_FATAL;
976 goto err;
977 }
978
979 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
980 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
981 err_code = ERR_ALERT | ERR_FATAL;
982 goto err;
983 }
984
985 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100986 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +0100987 if (repl && err) {
988 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
989 file, line, cmd, *err);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto err;
992 }
993
994 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
995 err_code |= ERR_WARN;
996
997 return err_code;
998 err:
999 free(preg);
1000 return err_code;
1001}
1002
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001004 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001005 * Returns the error code, 0 if OK, or any combination of :
1006 * - ERR_ABORT: must abort ASAP
1007 * - ERR_FATAL: we can continue parsing but not start the service
1008 * - ERR_WARN: a warning has been emitted
1009 * - ERR_ALERT: an alert has been emitted
1010 * Only the two first ones can stop processing, the two others are just
1011 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001013int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014{
1015 static struct proxy *curproxy = NULL;
1016 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001017 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001018 int rc;
1019 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001020 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001021 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (!strcmp(args[0], "listen"))
1024 rc = PR_CAP_LISTEN;
1025 else if (!strcmp(args[0], "frontend"))
1026 rc = PR_CAP_FE | PR_CAP_RS;
1027 else if (!strcmp(args[0], "backend"))
1028 rc = PR_CAP_BE | PR_CAP_RS;
1029 else if (!strcmp(args[0], "ruleset"))
1030 rc = PR_CAP_RS;
1031 else
1032 rc = PR_CAP_NONE;
1033
1034 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 if (!*args[1]) {
1036 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1037 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001039 err_code |= ERR_ALERT | ERR_ABORT;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001042
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001043 err = invalid_char(args[1]);
1044 if (err) {
1045 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1046 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001048 }
1049
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001050 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1051 /*
1052 * If there are two proxies with the same name only following
1053 * combinations are allowed:
1054 *
1055 * listen backend frontend ruleset
1056 * listen - - - -
1057 * backend - - OK -
1058 * frontend - OK - -
1059 * ruleset - - - -
1060 */
1061
1062 if (!strcmp(curproxy->id, args[1]) &&
1063 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1064 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001065 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1066 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1067 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001068 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001069 }
1070 }
1071
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001074 err_code |= ERR_ALERT | ERR_ABORT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001077
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 curproxy->next = proxy;
1080 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001081 curproxy->conf.file = file;
1082 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001083 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086
1087 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001088 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001089 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001090 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_FATAL;
1092 goto out;
1093 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001094 new = curproxy->listen;
1095 while (new != last) {
1096 new->conf.file = file;
1097 new->conf.line = linenum;
1098 new = new->next;
1099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 global.maxsock++;
1101 }
1102
1103 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001104 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001108 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001109 curproxy->no_options = defproxy.no_options;
1110 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001111 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001112 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001113 curproxy->except_net = defproxy.except_net;
1114 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001115 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001116 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001118 if (defproxy.fwdfor_hdr_len) {
1119 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1120 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1121 }
1122
Willy Tarreaub86db342009-11-30 11:50:16 +01001123 if (defproxy.orgto_hdr_len) {
1124 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1125 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1126 }
1127
Willy Tarreau977b8e42006-12-29 14:19:17 +01001128 if (curproxy->cap & PR_CAP_FE) {
1129 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001130 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001131 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001132
1133 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001134 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1135 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001136
1137 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139
Willy Tarreau977b8e42006-12-29 14:19:17 +01001140 if (curproxy->cap & PR_CAP_BE) {
1141 curproxy->fullconn = defproxy.fullconn;
1142 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143
Willy Tarreau977b8e42006-12-29 14:19:17 +01001144 if (defproxy.check_req)
1145 curproxy->check_req = strdup(defproxy.check_req);
1146 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (defproxy.cookie_name)
1149 curproxy->cookie_name = strdup(defproxy.cookie_name);
1150 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001151 if (defproxy.cookie_domain)
1152 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001153
Emeric Brun647caf12009-06-30 17:57:00 +02001154 if (defproxy.rdp_cookie_name)
1155 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1156 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1157
Willy Tarreau01732802007-11-01 22:48:15 +01001158 if (defproxy.url_param_name)
1159 curproxy->url_param_name = strdup(defproxy.url_param_name);
1160 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001161
Benoitaffb4812009-03-25 13:02:10 +01001162 if (defproxy.hh_name)
1163 curproxy->hh_name = strdup(defproxy.hh_name);
1164 curproxy->hh_len = defproxy.hh_len;
1165 curproxy->hh_match_domain = defproxy.hh_match_domain;
1166
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001167 if (defproxy.iface_name)
1168 curproxy->iface_name = strdup(defproxy.iface_name);
1169 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001172 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001173 if (defproxy.capture_name)
1174 curproxy->capture_name = strdup(defproxy.capture_name);
1175 curproxy->capture_namelen = defproxy.capture_namelen;
1176 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178
Willy Tarreau977b8e42006-12-29 14:19:17 +01001179 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001180 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001181 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001182 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001183 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 curproxy->uri_auth = defproxy.uri_auth;
1185 curproxy->mon_net = defproxy.mon_net;
1186 curproxy->mon_mask = defproxy.mon_mask;
1187 if (defproxy.monitor_uri)
1188 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1189 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001190 if (defproxy.defbe.name)
1191 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 }
1193
1194 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001195 curproxy->timeout.connect = defproxy.timeout.connect;
1196 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001197 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001198 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001199 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001200 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001201 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001202 curproxy->source_addr = defproxy.source_addr;
1203 }
1204
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 curproxy->mode = defproxy.mode;
1206 curproxy->logfac1 = defproxy.logfac1;
1207 curproxy->logsrv1 = defproxy.logsrv1;
1208 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001209 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 curproxy->logfac2 = defproxy.logfac2;
1211 curproxy->logsrv2 = defproxy.logsrv2;
1212 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001213 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001215 curproxy->conf.used_listener_id = EB_ROOT;
1216 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001217
Willy Tarreau93893792009-07-23 13:19:11 +02001218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1221 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001222 /* FIXME-20070101: we should do this too at the end of the
1223 * config parsing to free all default values.
1224 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001225 free(defproxy.check_req);
1226 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001227 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001228 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001229 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001230 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001231 free(defproxy.capture_name);
1232 free(defproxy.monitor_uri);
1233 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001234 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001235 free(defproxy.fwdfor_hdr_name);
1236 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001237 free(defproxy.orgto_hdr_name);
1238 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001239
Willy Tarreaua534fea2008-08-03 12:19:50 +02001240 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001241 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001242
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 /* we cannot free uri_auth because it might already be used */
1244 init_default_instance();
1245 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001246 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 }
1249 else if (curproxy == NULL) {
1250 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254
Willy Tarreau977b8e42006-12-29 14:19:17 +01001255
1256 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001258 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001259 int cur_arg;
1260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (curproxy == &defproxy) {
1262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268
1269 if (strchr(args[1], ':') == NULL) {
1270 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001275
1276 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001277 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001281
Willy Tarreau90a570f2009-10-04 20:54:54 +02001282 new_listen = curproxy->listen;
1283 while (new_listen != last_listen) {
1284 new_listen->conf.file = file;
1285 new_listen->conf.line = linenum;
1286 new_listen = new_listen->next;
1287 }
1288
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001289 cur_arg = 2;
1290 while (*(args[cur_arg])) {
1291 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1292#ifdef SO_BINDTODEVICE
1293 struct listener *l;
1294
1295 if (!*args[cur_arg + 1]) {
1296 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001300 }
1301
1302 for (l = curproxy->listen; l != last_listen; l = l->next)
1303 l->interface = strdup(args[cur_arg + 1]);
1304
1305 global.last_checks |= LSTCHK_NETADM;
1306
1307 cur_arg += 2;
1308 continue;
1309#else
1310 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1311 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001314#endif
1315 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001316 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1317#ifdef TCP_MAXSEG
1318 struct listener *l;
1319 int mss;
1320
1321 if (!*args[cur_arg + 1]) {
1322 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001326 }
1327
1328 mss = str2uic(args[cur_arg + 1]);
1329 if (mss < 1 || mss > 65535) {
1330 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001334 }
1335
1336 for (l = curproxy->listen; l != last_listen; l = l->next)
1337 l->maxseg = mss;
1338
1339 cur_arg += 2;
1340 continue;
1341#else
1342 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1343 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001346#endif
1347 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001348
1349 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1350#ifdef TCP_DEFER_ACCEPT
1351 struct listener *l;
1352
1353 for (l = curproxy->listen; l != last_listen; l = l->next)
1354 l->options |= LI_O_DEF_ACCEPT;
1355
1356 cur_arg ++;
1357 continue;
1358#else
1359 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1360 file, linenum, args[0], args[cur_arg]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363#endif
1364 }
1365
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001366 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001367#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001368 struct listener *l;
1369
1370 for (l = curproxy->listen; l != last_listen; l = l->next)
1371 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001372
1373 cur_arg ++;
1374 continue;
1375#else
1376 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1377 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001382
1383 if (!strcmp(args[cur_arg], "name")) {
1384 struct listener *l;
1385
1386 for (l = curproxy->listen; l != last_listen; l = l->next)
1387 l->name = strdup(args[cur_arg + 1]);
1388
1389 cur_arg += 2;
1390 continue;
1391 }
1392
1393 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001394 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001395 struct listener *l;
1396
1397 if (curproxy->listen->next != last_listen) {
1398 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1399 file, linenum, args[cur_arg]);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
1402 }
1403
1404 if (!*args[cur_arg + 1]) {
1405 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1406 file, linenum, args[cur_arg]);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto out;
1409 }
1410
1411 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001412 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001413
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001414 if (curproxy->listen->luid <= 0) {
1415 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001416 file, linenum);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001421 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1422 if (node) {
1423 l = container_of(node, struct listener, conf.id);
1424 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1425 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1430
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001431 cur_arg += 2;
1432 continue;
1433 }
1434
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001435 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001436 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
1443 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1444 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1445 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 /* flush useless bits */
1454 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001457 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001459 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460
Willy Tarreau1c47f852006-07-09 08:22:27 +02001461 if (!*args[1]) {
1462 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001466 }
1467
Willy Tarreaua534fea2008-08-03 12:19:50 +02001468 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001469 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001470 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001471 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001472 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1473
Willy Tarreau93893792009-07-23 13:19:11 +02001474 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1477 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1478 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1479 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1480 else {
1481 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
1485 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001486 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001487 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001488
1489 if (curproxy == &defproxy) {
1490 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001494 }
1495
1496 if (!*args[1]) {
1497 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001501 }
1502
1503 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001504 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001506 if (curproxy->uuid <= 0) {
1507 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001511 }
1512
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001513 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1514 if (node) {
1515 struct proxy *target = container_of(node, struct proxy, conf.id);
1516 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1517 file, linenum, proxy_type_str(curproxy), curproxy->id,
1518 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001523 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001524 else if (!strcmp(args[0], "description")) {
1525 int i, len=0;
1526 char *d;
1527
Cyril Bonté99ed3272010-01-24 23:29:44 +01001528 if (curproxy == &defproxy) {
1529 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1530 file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001535 if (!*args[1]) {
1536 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1537 file, linenum, args[0]);
1538 return -1;
1539 }
1540
1541 for(i=1; *args[i]; i++)
1542 len += strlen(args[i])+1;
1543
1544 d = (char *)calloc(1, len);
1545 curproxy->desc = d;
1546
1547 d += sprintf(d, "%s", args[1]);
1548 for(i=2; *args[i]; i++)
1549 d += sprintf(d, " %s", args[i]);
1550
1551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1553 curproxy->state = PR_STSTOPPED;
1554 }
1555 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1556 curproxy->state = PR_STNEW;
1557 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001558 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1559 int cur_arg = 1;
1560 unsigned int set = 0;
1561
1562 while (*args[cur_arg]) {
1563 int u;
1564 if (strcmp(args[cur_arg], "all") == 0) {
1565 set = 0;
1566 break;
1567 }
1568 else if (strcmp(args[cur_arg], "odd") == 0) {
1569 set |= 0x55555555;
1570 }
1571 else if (strcmp(args[cur_arg], "even") == 0) {
1572 set |= 0xAAAAAAAA;
1573 }
1574 else {
1575 u = str2uic(args[cur_arg]);
1576 if (u < 1 || u > 32) {
1577 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1578 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001581 }
1582 if (u > global.nbproc) {
1583 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001586 }
1587 set |= 1 << (u - 1);
1588 }
1589 cur_arg++;
1590 }
1591 curproxy->bind_proc = set;
1592 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001593 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001594 if (curproxy == &defproxy) {
1595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001598 }
1599
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001600 err = invalid_char(args[1]);
1601 if (err) {
1602 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1603 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001605 }
1606
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1608 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1609 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001612 }
1613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1615 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 if (*(args[1]) == 0) {
1621 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001627 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001628 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 curproxy->cookie_name = strdup(args[1]);
1630 curproxy->cookie_len = strlen(curproxy->cookie_name);
1631
1632 cur_arg = 2;
1633 while (*(args[cur_arg])) {
1634 if (!strcmp(args[cur_arg], "rewrite")) {
1635 curproxy->options |= PR_O_COOK_RW;
1636 }
1637 else if (!strcmp(args[cur_arg], "indirect")) {
1638 curproxy->options |= PR_O_COOK_IND;
1639 }
1640 else if (!strcmp(args[cur_arg], "insert")) {
1641 curproxy->options |= PR_O_COOK_INS;
1642 }
1643 else if (!strcmp(args[cur_arg], "nocache")) {
1644 curproxy->options |= PR_O_COOK_NOC;
1645 }
1646 else if (!strcmp(args[cur_arg], "postonly")) {
1647 curproxy->options |= PR_O_COOK_POST;
1648 }
1649 else if (!strcmp(args[cur_arg], "prefix")) {
1650 curproxy->options |= PR_O_COOK_PFX;
1651 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001652 else if (!strcmp(args[cur_arg], "domain")) {
1653 if (!*args[cur_arg + 1]) {
1654 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1655 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001658 }
1659
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001660 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001661 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001662 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1663 " dots nor does not start with a dot."
1664 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001665 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001666 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001667 }
1668
1669 err = invalid_domainchar(args[cur_arg + 1]);
1670 if (err) {
1671 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1672 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 }
1676
Willy Tarreau68a897b2009-12-03 23:28:34 +01001677 if (!curproxy->cookie_domain) {
1678 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1679 } else {
1680 /* one domain was already specified, add another one by
1681 * building the string which will be returned along with
1682 * the cookie.
1683 */
1684 char *new_ptr;
1685 int new_len = strlen(curproxy->cookie_domain) +
1686 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1687 new_ptr = malloc(new_len);
1688 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1689 free(curproxy->cookie_domain);
1690 curproxy->cookie_domain = new_ptr;
1691 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001692 cur_arg++;
1693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001695 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
1700 cur_arg++;
1701 }
1702 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1703 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707
1708 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1709 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1710 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001714 else if (!strcmp(args[0], "persist")) { /* persist */
1715 if (*(args[1]) == 0) {
1716 Alert("parsing [%s:%d] : missing persist method.\n",
1717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001720 }
1721
1722 if (!strncmp(args[1], "rdp-cookie", 10)) {
1723 curproxy->options2 |= PR_O2_RDPC_PRST;
1724
Emeric Brunb982a3d2010-01-04 15:45:53 +01001725 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001726 const char *beg, *end;
1727
1728 beg = args[1] + 11;
1729 end = strchr(beg, ')');
1730
1731 if (!end || end == beg) {
1732 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1733 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001736 }
1737
1738 free(curproxy->rdp_cookie_name);
1739 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1740 curproxy->rdp_cookie_len = end-beg;
1741 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001742 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001743 free(curproxy->rdp_cookie_name);
1744 curproxy->rdp_cookie_name = strdup("msts");
1745 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1746 }
1747 else { /* syntax */
1748 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1749 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001752 }
1753 }
1754 else {
1755 Alert("parsing [%s:%d] : unknown persist method.\n",
1756 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001759 }
1760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001762 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001764 if (curproxy == &defproxy) {
1765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768 }
1769
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001774 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001780 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 curproxy->appsession_name = strdup(args[1]);
1782 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1783 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001784 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1785 if (err) {
1786 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1787 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001790 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001791 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001792
Willy Tarreau51041c72007-09-09 21:56:53 +02001793 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1794 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_ABORT;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001798
1799 cur_arg = 6;
1800 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001801 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1802 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001803 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001804 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001805 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001806 } else if (!strcmp(args[cur_arg], "prefix")) {
1807 curproxy->options2 |= PR_O2_AS_PFX;
1808 } else if (!strcmp(args[cur_arg], "mode")) {
1809 if (!*args[cur_arg + 1]) {
1810 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1811 file, linenum, args[0], args[cur_arg]);
1812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
1815
1816 cur_arg++;
1817 if (!strcmp(args[cur_arg], "query-string")) {
1818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1819 curproxy->options2 |= PR_O2_AS_M_QS;
1820 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1821 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1822 curproxy->options2 |= PR_O2_AS_M_PP;
1823 } else {
1824 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001829 cur_arg++;
1830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 } /* Url App Session */
1832 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001833 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 if (*(args[4]) == 0) {
1844 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001849 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 curproxy->capture_name = strdup(args[2]);
1851 curproxy->capture_namelen = strlen(curproxy->capture_name);
1852 curproxy->capture_len = atol(args[4]);
1853 if (curproxy->capture_len >= CAPTURE_LEN) {
1854 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1855 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 curproxy->capture_len = CAPTURE_LEN - 1;
1858 }
1859 curproxy->to_log |= LW_COOKIE;
1860 }
1861 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1862 struct cap_hdr *hdr;
1863
1864 if (curproxy == &defproxy) {
1865 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 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
1869
1870 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1871 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1872 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 }
1876
1877 hdr = calloc(sizeof(struct cap_hdr), 1);
1878 hdr->next = curproxy->req_cap;
1879 hdr->name = strdup(args[3]);
1880 hdr->namelen = strlen(args[3]);
1881 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001882 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 hdr->index = curproxy->nb_req_cap++;
1884 curproxy->req_cap = hdr;
1885 curproxy->to_log |= LW_REQHDR;
1886 }
1887 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1888 struct cap_hdr *hdr;
1889
1890 if (curproxy == &defproxy) {
1891 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 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
1895
1896 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1897 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1898 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
1902 hdr = calloc(sizeof(struct cap_hdr), 1);
1903 hdr->next = curproxy->rsp_cap;
1904 hdr->name = strdup(args[3]);
1905 hdr->namelen = strlen(args[3]);
1906 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001907 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 hdr->index = curproxy->nb_rsp_cap++;
1909 curproxy->rsp_cap = hdr;
1910 curproxy->to_log |= LW_RSPHDR;
1911 }
1912 else {
1913 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\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 }
1918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 if (*(args[1]) == 0) {
1924 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
1929 curproxy->conn_retries = atol(args[1]);
1930 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001931 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1932 struct req_acl_rule *req_acl;
1933
1934 if (curproxy == &defproxy) {
1935 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940
1941 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1942 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1943 file, linenum, args[0]);
1944 err_code |= ERR_WARN;
1945 }
1946
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001947 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001948
1949 if (!req_acl) {
1950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
1952 }
1953
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001954 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001955 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1956 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001957 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001958 if (curproxy == &defproxy) {
1959 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001962 }
1963
Willy Tarreauef6494c2010-01-28 17:12:36 +01001964 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001965 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001969 }
1970
Willy Tarreauef6494c2010-01-28 17:12:36 +01001971 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001972 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1973 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001976 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001977
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001978 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001979 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001980 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001981 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001982 struct redirect_rule *rule;
1983 int cur_arg;
1984 int type = REDIRECT_TYPE_NONE;
1985 int code = 302;
1986 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001987 char *cookie = NULL;
1988 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001989 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001990
Cyril Bonté99ed3272010-01-24 23:29:44 +01001991 if (curproxy == &defproxy) {
1992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001997 cur_arg = 1;
1998 while (*(args[cur_arg])) {
1999 if (!strcmp(args[cur_arg], "location")) {
2000 if (!*args[cur_arg + 1]) {
2001 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2002 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002005 }
2006
2007 type = REDIRECT_TYPE_LOCATION;
2008 cur_arg++;
2009 destination = args[cur_arg];
2010 }
2011 else if (!strcmp(args[cur_arg], "prefix")) {
2012 if (!*args[cur_arg + 1]) {
2013 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2014 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002017 }
2018
2019 type = REDIRECT_TYPE_PREFIX;
2020 cur_arg++;
2021 destination = args[cur_arg];
2022 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002023 else if (!strcmp(args[cur_arg], "set-cookie")) {
2024 if (!*args[cur_arg + 1]) {
2025 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2026 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002029 }
2030
2031 cur_arg++;
2032 cookie = args[cur_arg];
2033 cookie_set = 1;
2034 }
2035 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2036 if (!*args[cur_arg + 1]) {
2037 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2038 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002041 }
2042
2043 cur_arg++;
2044 cookie = args[cur_arg];
2045 cookie_set = 0;
2046 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002047 else if (!strcmp(args[cur_arg],"code")) {
2048 if (!*args[cur_arg + 1]) {
2049 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002053 }
2054 cur_arg++;
2055 code = atol(args[cur_arg]);
2056 if (code < 301 || code > 303) {
2057 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2058 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002061 }
2062 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002063 else if (!strcmp(args[cur_arg],"drop-query")) {
2064 flags |= REDIRECT_FLAG_DROP_QS;
2065 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002066 else if (!strcmp(args[cur_arg],"append-slash")) {
2067 flags |= REDIRECT_FLAG_APPEND_SLASH;
2068 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002069 else if (strcmp(args[cur_arg], "if") == 0 ||
2070 strcmp(args[cur_arg], "unless") == 0) {
2071 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2072 if (!cond) {
2073 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2074 file, linenum, args[0]);
2075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
2077 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002078 break;
2079 }
2080 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002081 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002082 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002085 }
2086 cur_arg++;
2087 }
2088
2089 if (type == REDIRECT_TYPE_NONE) {
2090 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002094 }
2095
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002096 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2097 rule->cond = cond;
2098 rule->rdr_str = strdup(destination);
2099 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002100 if (cookie) {
2101 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2102 * a clear consists in appending "; Max-Age=0" at the end.
2103 */
2104 rule->cookie_len = strlen(cookie);
2105 if (cookie_set)
2106 rule->cookie_str = strdup(cookie);
2107 else {
2108 rule->cookie_str = malloc(rule->cookie_len + 12);
2109 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2110 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2111 rule->cookie_len += 11;
2112 }
2113 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002114 rule->type = type;
2115 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002116 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002117 LIST_INIT(&rule->list);
2118 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002119 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002120 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002121 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002122 struct switching_rule *rule;
2123
Willy Tarreaub099aca2008-10-12 17:26:37 +02002124 if (curproxy == &defproxy) {
2125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002128 }
2129
Willy Tarreau55ea7572007-06-17 19:56:27 +02002130 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002132
2133 if (*(args[1]) == 0) {
2134 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002137 }
2138
Willy Tarreauef6494c2010-01-28 17:12:36 +01002139 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002140 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002144 }
2145
Willy Tarreauef6494c2010-01-28 17:12:36 +01002146 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002147 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002148 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002151 }
2152
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002153 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002154
Willy Tarreau55ea7572007-06-17 19:56:27 +02002155 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2156 rule->cond = cond;
2157 rule->be.name = strdup(args[1]);
2158 LIST_INIT(&rule->list);
2159 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2160 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002161 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002162 struct force_persist_rule *rule;
2163
2164 if (curproxy == &defproxy) {
2165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169
2170 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2171 err_code |= ERR_WARN;
2172
Willy Tarreauef6494c2010-01-28 17:12:36 +01002173 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002174 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2175 file, linenum, args[0]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
Willy Tarreauef6494c2010-01-28 17:12:36 +01002180 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002181 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2182 file, linenum);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002187 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002188
2189 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2190 rule->cond = cond;
2191 LIST_INIT(&rule->list);
2192 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002194 else if (!strcmp(args[0], "stick-table")) {
2195 int myidx = 1;
2196
2197 curproxy->table.type = (unsigned int)-1;
2198 while (*args[myidx]) {
2199 const char *err;
2200
2201 if (strcmp(args[myidx], "size") == 0) {
2202 myidx++;
2203 if (!*(args[myidx])) {
2204 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2205 file, linenum, args[myidx-1]);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2210 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2211 file, linenum, *err, args[myidx-1]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002215 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002216 }
2217 else if (strcmp(args[myidx], "expire") == 0) {
2218 myidx++;
2219 if (!*(args[myidx])) {
2220 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2221 file, linenum, args[myidx-1]);
2222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
2224 }
2225 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2226 if (err) {
2227 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2228 file, linenum, *err, args[myidx-1]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002233 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002234 }
2235 else if (strcmp(args[myidx], "nopurge") == 0) {
2236 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002237 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002238 }
2239 else if (strcmp(args[myidx], "type") == 0) {
2240 myidx++;
2241 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2242 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2243 file, linenum, args[myidx]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002247 /* myidx already points to next arg */
2248 }
2249 else {
2250 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2251 file, linenum, args[myidx]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002254 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002255 }
2256
2257 if (!curproxy->table.size) {
2258 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2259 file, linenum);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
2264 if (curproxy->table.type == (unsigned int)-1) {
2265 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2266 file, linenum);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270 }
2271 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002272 struct sticking_rule *rule;
2273 struct pattern_expr *expr;
2274 int myidx = 0;
2275 const char *name = NULL;
2276 int flags;
2277
2278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2285 err_code |= ERR_WARN;
2286 goto out;
2287 }
2288
2289 myidx++;
2290 if ((strcmp(args[myidx], "store") == 0) ||
2291 (strcmp(args[myidx], "store-request") == 0)) {
2292 myidx++;
2293 flags = STK_IS_STORE;
2294 }
2295 else if (strcmp(args[myidx], "store-response") == 0) {
2296 myidx++;
2297 flags = STK_IS_STORE | STK_ON_RSP;
2298 }
2299 else if (strcmp(args[myidx], "match") == 0) {
2300 myidx++;
2301 flags = STK_IS_MATCH;
2302 }
2303 else if (strcmp(args[myidx], "on") == 0) {
2304 myidx++;
2305 flags = STK_IS_MATCH | STK_IS_STORE;
2306 }
2307 else {
2308 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 if (*(args[myidx]) == 0) {
2314 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 expr = pattern_parse_expr(args, &myidx);
2320 if (!expr) {
2321 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325
2326 if (flags & STK_ON_RSP) {
2327 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2328 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2329 file, linenum, args[0], expr->fetch->kw);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 } else {
2334 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2335 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2336 file, linenum, args[0], expr->fetch->kw);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 }
2341
2342 if (strcmp(args[myidx], "table") == 0) {
2343 myidx++;
2344 name = args[myidx++];
2345 }
2346
Willy Tarreauef6494c2010-01-28 17:12:36 +01002347 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2348 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002349 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2350 file, linenum, args[0]);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002354 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002355 else if (*(args[myidx])) {
2356 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2357 file, linenum, args[0], args[myidx]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002362 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2363
Emeric Brunb982a3d2010-01-04 15:45:53 +01002364 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2365 rule->cond = cond;
2366 rule->expr = expr;
2367 rule->flags = flags;
2368 rule->table.name = name ? strdup(name) : NULL;
2369 LIST_INIT(&rule->list);
2370 if (flags & STK_ON_RSP)
2371 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2372 else
2373 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2380 curproxy->uri_auth = NULL; /* we must detach from the default config */
2381
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002382 if (!*args[1]) {
2383 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 } else if (!strcmp(args[1], "uri")) {
2385 if (*(args[2]) == 0) {
2386 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 } else if (!strcmp(args[1], "realm")) {
2395 if (*(args[2]) == 0) {
2396 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002404 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002405 unsigned interval;
2406
2407 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2408 if (err) {
2409 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2410 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002413 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_ABORT;
2416 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002417 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002418 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2419 struct req_acl_rule *req_acl;
2420
2421 if (curproxy == &defproxy) {
2422 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2428 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2429 err_code |= ERR_ALERT | ERR_ABORT;
2430 goto out;
2431 }
2432
2433 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2434 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2435 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2436 file, linenum, args[0]);
2437 err_code |= ERR_WARN;
2438 }
2439
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002440 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002441
2442 if (!req_acl) {
2443 err_code |= ERR_ALERT | ERR_ABORT;
2444 goto out;
2445 }
2446
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002447 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002448 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 } else if (!strcmp(args[1], "auth")) {
2451 if (*(args[2]) == 0) {
2452 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
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 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_ABORT;
2458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
2460 } else if (!strcmp(args[1], "scope")) {
2461 if (*(args[2]) == 0) {
2462 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2466 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_ABORT;
2468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 } else if (!strcmp(args[1], "enable")) {
2471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2472 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_ABORT;
2474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002476 } else if (!strcmp(args[1], "hide-version")) {
2477 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2478 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_ABORT;
2480 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002481 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002482 } else if (!strcmp(args[1], "show-legends")) {
2483 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2485 err_code |= ERR_ALERT | ERR_ABORT;
2486 goto out;
2487 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002488 } else if (!strcmp(args[1], "show-node")) {
2489
2490 if (*args[2]) {
2491 int i;
2492 char c;
2493
2494 for (i=0; args[2][i]; i++) {
2495 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002496 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002497 break;
2498 }
2499
2500 if (!i || args[2][i]) {
2501 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2502 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2503 file, linenum, args[0], args[1]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 }
2508
2509 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2510 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2511 err_code |= ERR_ALERT | ERR_ABORT;
2512 goto out;
2513 }
2514 } else if (!strcmp(args[1], "show-desc")) {
2515 char *desc = NULL;
2516
2517 if (*args[2]) {
2518 int i, len=0;
2519 char *d;
2520
2521 for(i=2; *args[i]; i++)
2522 len += strlen(args[i])+1;
2523
2524 desc = d = (char *)calloc(1, len);
2525
2526 d += sprintf(d, "%s", args[2]);
2527 for(i=3; *args[i]; i++)
2528 d += sprintf(d, " %s", args[i]);
2529 }
2530
2531 if (!*args[2] && !global.desc)
2532 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2533 file, linenum, args[1]);
2534 else {
2535 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2536 free(desc);
2537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2538 err_code |= ERR_ALERT | ERR_ABORT;
2539 goto out;
2540 }
2541 free(desc);
2542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002544stats_error_parsing:
2545 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2546 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550 }
2551 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002552 int optnum;
2553
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002554 if (*(args[1]) == '\0') {
2555 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002560
2561 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2562 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002563 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2564 err_code |= ERR_WARN;
2565 goto out;
2566 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002567
Willy Tarreau3842f002009-06-14 11:39:52 +02002568 curproxy->no_options &= ~cfg_opts[optnum].val;
2569 curproxy->options &= ~cfg_opts[optnum].val;
2570
2571 switch (kwm) {
2572 case KWM_STD:
2573 curproxy->options |= cfg_opts[optnum].val;
2574 break;
2575 case KWM_NO:
2576 curproxy->no_options |= cfg_opts[optnum].val;
2577 break;
2578 case KWM_DEF: /* already cleared */
2579 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002580 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002581
Willy Tarreau93893792009-07-23 13:19:11 +02002582 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002583 }
2584 }
2585
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002586 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2587 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002588 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2589 err_code |= ERR_WARN;
2590 goto out;
2591 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002592
Willy Tarreau3842f002009-06-14 11:39:52 +02002593 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2594 curproxy->options2 &= ~cfg_opts2[optnum].val;
2595
2596 switch (kwm) {
2597 case KWM_STD:
2598 curproxy->options2 |= cfg_opts2[optnum].val;
2599 break;
2600 case KWM_NO:
2601 curproxy->no_options2 |= cfg_opts2[optnum].val;
2602 break;
2603 case KWM_DEF: /* already cleared */
2604 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002605 }
Willy Tarreau93893792009-07-23 13:19:11 +02002606 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002607 }
2608 }
2609
Willy Tarreau3842f002009-06-14 11:39:52 +02002610 if (kwm != KWM_STD) {
2611 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002612 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002615 }
2616
Emeric Brun3a058f32009-06-30 18:26:00 +02002617 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002619 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002621 if (*(args[2]) != '\0') {
2622 if (!strcmp(args[2], "clf")) {
2623 curproxy->options2 |= PR_O2_CLFLOG;
2624 } else {
2625 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002628 }
2629 }
2630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 else if (!strcmp(args[1], "tcplog"))
2632 /* generate a detailed TCP log */
2633 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 else if (!strcmp(args[1], "tcpka")) {
2635 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002636 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002638
2639 if (curproxy->cap & PR_CAP_FE)
2640 curproxy->options |= PR_O_TCP_CLI_KA;
2641 if (curproxy->cap & PR_CAP_BE)
2642 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_WARN;
2647
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002649 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002650 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002651 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002652 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002653 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 if (!*args[2]) { /* no argument */
2655 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2656 curproxy->check_len = strlen(DEF_CHECK_REQ);
2657 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002658 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 curproxy->check_req = (char *)malloc(reqlen);
2660 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002661 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002663 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 if (*args[4])
2665 reqlen += strlen(args[4]);
2666 else
2667 reqlen += strlen("HTTP/1.0");
2668
2669 curproxy->check_req = (char *)malloc(reqlen);
2670 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002671 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002673 }
2674 else if (!strcmp(args[1], "ssl-hello-chk")) {
2675 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002678
Willy Tarreaua534fea2008-08-03 12:19:50 +02002679 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002680 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002681 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002682 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002683 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
Willy Tarreau23677902007-05-08 23:50:35 +02002685 else if (!strcmp(args[1], "smtpchk")) {
2686 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002687 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002688 curproxy->options &= ~PR_O_HTTP_CHK;
2689 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002690 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002691 curproxy->options |= PR_O_SMTP_CHK;
2692
2693 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2694 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2695 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2696 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2697 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2698 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2699 curproxy->check_req = (char *)malloc(reqlen);
2700 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2701 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2702 } else {
2703 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2704 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2705 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2706 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2707 }
2708 }
2709 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002710 else if (!strcmp(args[1], "mysql-check")) {
2711 /* use MYSQL request to check servers' health */
2712 free(curproxy->check_req);
2713 curproxy->options &= ~PR_O_HTTP_CHK;
2714 curproxy->options &= ~PR_O_SSL3_CHK;
2715 curproxy->options &= ~PR_O_SMTP_CHK;
2716 curproxy->options2 |= PR_O2_MYSQL_CHK;
2717 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002718 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002719 int cur_arg;
2720
2721 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2722 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002723 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002724
2725 curproxy->options |= PR_O_FWDFOR;
2726
2727 free(curproxy->fwdfor_hdr_name);
2728 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2729 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2730
2731 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2732 cur_arg = 2;
2733 while (*(args[cur_arg])) {
2734 if (!strcmp(args[cur_arg], "except")) {
2735 /* suboption except - needs additional argument for it */
2736 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2737 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2738 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002741 }
2742 /* flush useless bits */
2743 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002744 cur_arg += 2;
2745 } else if (!strcmp(args[cur_arg], "header")) {
2746 /* suboption header - needs additional argument for it */
2747 if (*(args[cur_arg+1]) == 0) {
2748 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2749 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002752 }
2753 free(curproxy->fwdfor_hdr_name);
2754 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2755 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2756 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002757 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002758 /* unknown suboption - catchall */
2759 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2760 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002763 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002764 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002765 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002766 else if (!strcmp(args[1], "originalto")) {
2767 int cur_arg;
2768
2769 /* insert x-original-to field, but not for the IP address listed as an except.
2770 * set default options (ie: bitfield, header name, etc)
2771 */
2772
2773 curproxy->options |= PR_O_ORGTO;
2774
2775 free(curproxy->orgto_hdr_name);
2776 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2777 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2778
2779 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2780 cur_arg = 2;
2781 while (*(args[cur_arg])) {
2782 if (!strcmp(args[cur_arg], "except")) {
2783 /* suboption except - needs additional argument for it */
2784 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2785 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2786 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002789 }
2790 /* flush useless bits */
2791 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2792 cur_arg += 2;
2793 } else if (!strcmp(args[cur_arg], "header")) {
2794 /* suboption header - needs additional argument for it */
2795 if (*(args[cur_arg+1]) == 0) {
2796 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2797 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002800 }
2801 free(curproxy->orgto_hdr_name);
2802 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2803 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2804 cur_arg += 2;
2805 } else {
2806 /* unknown suboption - catchall */
2807 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2808 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002811 }
2812 } /* end while loop */
2813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002814 else {
2815 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 }
Willy Tarreau93893792009-07-23 13:19:11 +02002819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002821 else if (!strcmp(args[0], "default_backend")) {
2822 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002824
2825 if (*(args[1]) == 0) {
2826 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002829 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002830 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002831 curproxy->defbe.name = strdup(args[1]);
2832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002836
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002837 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2838 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 /* enable reconnections to dispatch */
2841 curproxy->options |= PR_O_REDISP;
2842 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002843 else if (!strcmp(args[0], "http-check")) {
2844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002846
2847 if (strcmp(args[1], "disable-on-404") == 0) {
2848 /* enable a graceful server shutdown on an HTTP 404 response */
2849 curproxy->options |= PR_O_DISABLE404;
2850 }
Willy Tarreauef781042010-01-27 11:53:01 +01002851 else if (strcmp(args[1], "send-state") == 0) {
2852 /* enable emission of the apparent state of a server in HTTP checks */
2853 curproxy->options2 |= PR_O2_CHK_SNDST;
2854 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002855 else {
2856 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002859 }
2860 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002861 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002862 if (curproxy == &defproxy) {
2863 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002866 }
2867
Willy Tarreaub80c2302007-11-30 20:51:32 +01002868 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002870
2871 if (strcmp(args[1], "fail") == 0) {
2872 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002873 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002874 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2875 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002878 }
2879
Willy Tarreauef6494c2010-01-28 17:12:36 +01002880 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002881 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2882 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002885 }
2886 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2887 }
2888 else {
2889 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002892 }
2893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894#ifdef TPROXY
2895 else if (!strcmp(args[0], "transparent")) {
2896 /* enable transparent proxy connections */
2897 curproxy->options |= PR_O_TRANSP;
2898 }
2899#endif
2900 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002901 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 if (*(args[1]) == 0) {
2905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
2909 curproxy->maxconn = atol(args[1]);
2910 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002911 else if (!strcmp(args[0], "backlog")) { /* backlog */
2912 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002913 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002914
2915 if (*(args[1]) == 0) {
2916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002919 }
2920 curproxy->backlog = atol(args[1]);
2921 }
Willy Tarreau86034312006-12-29 00:10:33 +01002922 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
Willy Tarreau86034312006-12-29 00:10:33 +01002926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002930 }
2931 curproxy->fullconn = atol(args[1]);
2932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002939 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2940 if (err) {
2941 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2942 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002945 }
2946 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
2948 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2949 if (curproxy == &defproxy) {
2950 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002954 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 if (strchr(args[1], ':') == NULL) {
2958 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 }
2962 curproxy->dispatch_addr = *str2sa(args[1]);
2963 }
2964 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002967
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002968 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002969 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2970 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002975 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2976 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2977 err_code |= ERR_WARN;
2978
2979 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2980 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2981 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2982 }
2983 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2984 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2985 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2986 }
2987 else {
2988 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002993 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002995 char *rport, *raddr;
2996 short realport = 0;
2997 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002999 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003004 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003006
3007 if (!*args[2]) {
3008 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3009 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003013
3014 err = invalid_char(args[1]);
3015 if (err) {
3016 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3017 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003020 }
3021
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3023 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_ABORT;
3025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 }
3027
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003028 if (!defsrv) {
3029 /* the servers are linked backwards first */
3030 newsrv->next = curproxy->srv;
3031 curproxy->srv = newsrv;
3032 newsrv->proxy = curproxy;
3033 newsrv->conf.file = file;
3034 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003036 LIST_INIT(&newsrv->pendconns);
3037 do_check = 0;
3038 newsrv->state = SRV_RUNNING; /* early server setup */
3039 newsrv->last_change = now.tv_sec;
3040 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003042 /* several ways to check the port component :
3043 * - IP => port=+0, relative
3044 * - IP: => port=+0, relative
3045 * - IP:N => port=N, absolute
3046 * - IP:+N => port=+N, relative
3047 * - IP:-N => port=-N, relative
3048 */
3049 raddr = strdup(args[2]);
3050 rport = strchr(raddr, ':');
3051 if (rport) {
3052 *rport++ = 0;
3053 realport = atol(rport);
3054 if (!isdigit((unsigned char)*rport))
3055 newsrv->state |= SRV_MAPPORTS;
3056 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003058
3059 newsrv->addr = *str2sa(raddr);
3060 newsrv->addr.sin_port = htons(realport);
3061 free(raddr);
3062
3063 newsrv->check_port = curproxy->defsrv.check_port;
3064 newsrv->inter = curproxy->defsrv.inter;
3065 newsrv->fastinter = curproxy->defsrv.fastinter;
3066 newsrv->downinter = curproxy->defsrv.downinter;
3067 newsrv->rise = curproxy->defsrv.rise;
3068 newsrv->fall = curproxy->defsrv.fall;
3069 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3070 newsrv->minconn = curproxy->defsrv.minconn;
3071 newsrv->maxconn = curproxy->defsrv.maxconn;
3072 newsrv->slowstart = curproxy->defsrv.slowstart;
3073 newsrv->onerror = curproxy->defsrv.onerror;
3074 newsrv->consecutive_errors_limit
3075 = curproxy->defsrv.consecutive_errors_limit;
3076 newsrv->uweight = newsrv->iweight
3077 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003079 newsrv->curfd = -1; /* no health-check in progress */
3080 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003082 cur_arg = 3;
3083 } else {
3084 newsrv = &curproxy->defsrv;
3085 cur_arg = 1;
3086 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003087
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003089 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003090 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003091
3092 if (!*args[cur_arg + 1]) {
3093 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3094 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003097 }
3098
3099 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003100 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003101
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003102 if (newsrv->puid <= 0) {
3103 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003104 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003107 }
3108
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003109 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3110 if (node) {
3111 struct server *target = container_of(node, struct server, conf.id);
3112 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3113 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003118 cur_arg += 2;
3119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003120 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 newsrv->cookie = strdup(args[cur_arg + 1]);
3122 newsrv->cklen = strlen(args[cur_arg + 1]);
3123 cur_arg += 2;
3124 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003125 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003126 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3127 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3128 cur_arg += 2;
3129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003131 if (!*args[cur_arg + 1]) {
3132 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3133 file, linenum, args[cur_arg]);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
3137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003139 if (newsrv->rise <= 0) {
3140 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3141 file, linenum, args[cur_arg]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 newsrv->health = newsrv->rise;
3147 cur_arg += 2;
3148 }
3149 else if (!strcmp(args[cur_arg], "fall")) {
3150 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003151
3152 if (!*args[cur_arg + 1]) {
3153 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3154 file, linenum, args[cur_arg]);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158
3159 if (newsrv->fall <= 0) {
3160 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3161 file, linenum, args[cur_arg]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 cur_arg += 2;
3167 }
3168 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003169 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3170 if (err) {
3171 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3172 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003175 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003176 if (val <= 0) {
3177 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3178 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003181 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003182 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 cur_arg += 2;
3184 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003185 else if (!strcmp(args[cur_arg], "fastinter")) {
3186 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3187 if (err) {
3188 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3189 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003192 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003193 if (val <= 0) {
3194 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3195 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003198 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003199 newsrv->fastinter = val;
3200 cur_arg += 2;
3201 }
3202 else if (!strcmp(args[cur_arg], "downinter")) {
3203 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3204 if (err) {
3205 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3206 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003209 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003210 if (val <= 0) {
3211 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3212 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003215 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003216 newsrv->downinter = val;
3217 cur_arg += 2;
3218 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003219 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003220 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003221 cur_arg += 2;
3222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 else if (!strcmp(args[cur_arg], "port")) {
3224 newsrv->check_port = atol(args[cur_arg + 1]);
3225 cur_arg += 2;
3226 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003227 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 newsrv->state |= SRV_BACKUP;
3229 cur_arg ++;
3230 }
3231 else if (!strcmp(args[cur_arg], "weight")) {
3232 int w;
3233 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003234 if (w < 0 || w > 256) {
3235 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003240 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 cur_arg += 2;
3242 }
3243 else if (!strcmp(args[cur_arg], "minconn")) {
3244 newsrv->minconn = atol(args[cur_arg + 1]);
3245 cur_arg += 2;
3246 }
3247 else if (!strcmp(args[cur_arg], "maxconn")) {
3248 newsrv->maxconn = atol(args[cur_arg + 1]);
3249 cur_arg += 2;
3250 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003251 else if (!strcmp(args[cur_arg], "maxqueue")) {
3252 newsrv->maxqueue = atol(args[cur_arg + 1]);
3253 cur_arg += 2;
3254 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003255 else if (!strcmp(args[cur_arg], "slowstart")) {
3256 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003257 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003258 if (err) {
3259 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3260 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003263 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003264 if (val <= 0) {
3265 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3266 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003269 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003270 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003271 cur_arg += 2;
3272 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003273 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003274
3275 if (!*args[cur_arg + 1]) {
3276 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3277 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003280 }
3281
3282 newsrv->trackit = strdup(args[cur_arg + 1]);
3283
3284 cur_arg += 2;
3285 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003286 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 global.maxsock++;
3288 do_check = 1;
3289 cur_arg += 1;
3290 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003291 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003292 if (!strcmp(args[cur_arg + 1], "none"))
3293 newsrv->observe = HANA_OBS_NONE;
3294 else if (!strcmp(args[cur_arg + 1], "layer4"))
3295 newsrv->observe = HANA_OBS_LAYER4;
3296 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3297 if (curproxy->mode != PR_MODE_HTTP) {
3298 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3299 file, linenum, args[cur_arg + 1]);
3300 err_code |= ERR_ALERT;
3301 }
3302 newsrv->observe = HANA_OBS_LAYER7;
3303 }
3304 else {
3305 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3306 "'l4events', 'http-responses' but get '%s'\n",
3307 file, linenum, args[cur_arg], args[cur_arg + 1]);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311
3312 cur_arg += 2;
3313 }
3314 else if (!strcmp(args[cur_arg], "on-error")) {
3315 if (!strcmp(args[cur_arg + 1], "fastinter"))
3316 newsrv->onerror = HANA_ONERR_FASTINTER;
3317 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3318 newsrv->onerror = HANA_ONERR_FAILCHK;
3319 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3320 newsrv->onerror = HANA_ONERR_SUDDTH;
3321 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3322 newsrv->onerror = HANA_ONERR_MARKDWN;
3323 else {
3324 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3325 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3326 file, linenum, args[cur_arg], args[cur_arg + 1]);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
3330
3331 cur_arg += 2;
3332 }
3333 else if (!strcmp(args[cur_arg], "error-limit")) {
3334 if (!*args[cur_arg + 1]) {
3335 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3336 file, linenum, args[cur_arg]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
3340
3341 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3342
3343 if (newsrv->consecutive_errors_limit <= 0) {
3344 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3345 file, linenum, args[cur_arg]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003350 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003351 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003353#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003354 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003355 file, linenum, "source", "usesrc");
3356#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003357 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003359#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
3363 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003364 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3365
3366 if (port_low != port_high) {
3367 int i;
3368 if (port_low <= 0 || port_low > 65535 ||
3369 port_high <= 0 || port_high > 65535 ||
3370 port_low > port_high) {
3371 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3372 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003375 }
3376 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3377 for (i = 0; i < newsrv->sport_range->size; i++)
3378 newsrv->sport_range->ports[i] = port_low + i;
3379 }
3380
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003382 while (*(args[cur_arg])) {
3383 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003384#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3385#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003386 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3387 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3388 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003391 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003392#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003393 if (!*args[cur_arg + 1]) {
3394 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3395 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003398 }
3399 if (!strcmp(args[cur_arg + 1], "client")) {
3400 newsrv->state |= SRV_TPROXY_CLI;
3401 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3402 newsrv->state |= SRV_TPROXY_CIP;
3403 } else {
3404 newsrv->state |= SRV_TPROXY_ADDR;
3405 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3406 }
3407 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003408#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003409 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003410#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003411 cur_arg += 2;
3412 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003413#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003414 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003415 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003418#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3419 } /* "usesrc" */
3420
3421 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3422#ifdef SO_BINDTODEVICE
3423 if (!*args[cur_arg + 1]) {
3424 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3425 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003428 }
3429 if (newsrv->iface_name)
3430 free(newsrv->iface_name);
3431
3432 newsrv->iface_name = strdup(args[cur_arg + 1]);
3433 newsrv->iface_len = strlen(newsrv->iface_name);
3434 global.last_checks |= LSTCHK_NETADM;
3435#else
3436 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3437 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003440#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003441 cur_arg += 2;
3442 continue;
3443 }
3444 /* this keyword in not an option of "source" */
3445 break;
3446 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003448 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003449 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3450 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003454 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003455 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003456 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003457 file, linenum, newsrv->id);
3458 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003459 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003460 file, linenum);
3461
Willy Tarreau93893792009-07-23 13:19:11 +02003462 err_code |= ERR_ALERT | ERR_FATAL;
3463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 }
3465 }
3466
3467 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003468 if (newsrv->trackit) {
3469 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3470 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003473 }
3474
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003475 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3476 newsrv->check_port = newsrv->check_addr.sin_port;
3477
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3479 newsrv->check_port = realport; /* by default */
3480 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003481 /* not yet valid, because no port was set on
3482 * the server either. We'll check if we have
3483 * a known port on the first listener.
3484 */
3485 struct listener *l;
3486 l = curproxy->listen;
3487 if (l) {
3488 int port;
3489 port = (l->addr.ss_family == AF_INET6)
3490 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3491 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3492 newsrv->check_port = port;
3493 }
3494 }
3495 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3497 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003501
3502 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 newsrv->state |= SRV_CHECKED;
3504 }
3505
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003506 if (!defsrv) {
3507 if (newsrv->state & SRV_BACKUP)
3508 curproxy->srv_bck++;
3509 else
3510 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003511
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003512 newsrv->prev_state = newsrv->state;
3513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003516 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 int facility;
3518
3519 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3520 curproxy->logfac1 = global.logfac1;
3521 curproxy->logsrv1 = global.logsrv1;
3522 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003523 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 curproxy->logfac2 = global.logfac2;
3525 curproxy->logsrv2 = global.logsrv2;
3526 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003527 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
3529 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003530 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531
3532 facility = get_log_facility(args[2]);
3533 if (facility < 0) {
3534 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3535 exit(1);
3536 }
3537
3538 level = 7; /* max syslog level = debug */
3539 if (*(args[3])) {
3540 level = get_log_level(args[3]);
3541 if (level < 0) {
3542 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3543 exit(1);
3544 }
3545 }
3546
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003547 minlvl = 0; /* limit syslog level to this level (emerg) */
3548 if (*(args[4])) {
3549 minlvl = get_log_level(args[4]);
3550 if (level < 0) {
3551 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3552 exit(1);
3553 }
3554 }
3555
Robert Tsai81ae1952007-12-05 10:47:29 +01003556 if (args[1][0] == '/') {
3557 logsrv.u.addr.sa_family = AF_UNIX;
3558 logsrv.u.un = *str2sun(args[1]);
3559 } else {
3560 logsrv.u.addr.sa_family = AF_INET;
3561 logsrv.u.in = *str2sa(args[1]);
3562 if (!logsrv.u.in.sin_port) {
3563 logsrv.u.in.sin_port =
3564 htons(SYSLOG_PORT);
3565 }
3566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567
3568 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003569 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 curproxy->logfac1 = facility;
3571 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003572 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 }
3574 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003575 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 curproxy->logfac2 = facility;
3577 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003578 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 }
3580 else {
3581 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 }
3585 }
3586 else {
3587 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3588 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592 }
3593 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003594 int cur_arg;
3595
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003598
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003600 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3601 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003605
3606 /* we must first clear any optional default setting */
3607 curproxy->options &= ~PR_O_TPXY_MASK;
3608 free(curproxy->iface_name);
3609 curproxy->iface_name = NULL;
3610 curproxy->iface_len = 0;
3611
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 curproxy->source_addr = *str2sa(args[1]);
3613 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003614
3615 cur_arg = 2;
3616 while (*(args[cur_arg])) {
3617 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003618#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3619#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003620 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3621 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3622 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003625 }
3626#endif
3627 if (!*args[cur_arg + 1]) {
3628 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3629 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_ALERT | ERR_FATAL;
3631 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003632 }
3633
3634 if (!strcmp(args[cur_arg + 1], "client")) {
3635 curproxy->options |= PR_O_TPXY_CLI;
3636 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3637 curproxy->options |= PR_O_TPXY_CIP;
3638 } else {
3639 curproxy->options |= PR_O_TPXY_ADDR;
3640 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3641 }
3642 global.last_checks |= LSTCHK_NETADM;
3643#if !defined(CONFIG_HAP_LINUX_TPROXY)
3644 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003645#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003646#else /* no TPROXY support */
3647 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003648 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003651#endif
3652 cur_arg += 2;
3653 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003654 }
3655
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003656 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3657#ifdef SO_BINDTODEVICE
3658 if (!*args[cur_arg + 1]) {
3659 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003663 }
3664 if (curproxy->iface_name)
3665 free(curproxy->iface_name);
3666
3667 curproxy->iface_name = strdup(args[cur_arg + 1]);
3668 curproxy->iface_len = strlen(curproxy->iface_name);
3669 global.last_checks |= LSTCHK_NETADM;
3670#else
3671 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3672 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003675#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003676 cur_arg += 2;
3677 continue;
3678 }
3679 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3680 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003685 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3686 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3687 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003692 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3694 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003698
3699 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3700 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003701 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003702 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003706 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3707 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003708 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003709 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 }
3712 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003713 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3714 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003715 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003716 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
3719 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003720 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3721 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003722 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003723 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 }
3726 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003727 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3728 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003729 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003730 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003733 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003734 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3735 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003736 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003737 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003738 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003739 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003740 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003741 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3742 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003743 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003744 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003745 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003746 }
3747 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003748 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3749 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003750 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003751 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003752 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003755 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3757 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003761
3762 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3763 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003764 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003765 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 }
3768 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003769 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3770 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003771 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003772 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 }
3775 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003776 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3777 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003778 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003779 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
3782 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003783 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3784 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003785 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003786 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003790 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3791 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003792 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003793 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003796 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3798 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003799 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003800 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003801 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003804 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003805
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 if (curproxy == &defproxy) {
3807 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003811 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 if (*(args[1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003819
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003820 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3821 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3822 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3823 file, linenum, args[0]);
3824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3828 }
3829 else if (*args[2]) {
3830 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3831 file, linenum, args[0], args[2]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003836 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003837 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003838 wl->s = strdup(args[1]);
3839 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003840 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003843 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003849
Willy Tarreauade5ec42010-01-28 19:33:49 +01003850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3851 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003852 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003853 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 }
3856 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003857 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3858 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003859 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003860 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
3863 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003864 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3865 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003866 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003867 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
3870 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003871 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3873 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877
Willy Tarreauade5ec42010-01-28 19:33:49 +01003878 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3879 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003880 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003881 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 }
3884 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003885 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3886 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003887 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003888 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
3891 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003892 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3893 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003894 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003895 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
3898 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003899 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003900
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 if (curproxy == &defproxy) {
3902 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003906 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 if (*(args[1]) == 0) {
3910 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 }
3914
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003915 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3916 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3917 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3918 file, linenum, args[0]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922 err_code |= warnif_cond_requires_req(cond, file, linenum);
3923 }
3924 else if (*args[2]) {
3925 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3926 file, linenum, args[0], args[2]);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003931 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003932 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003933 wl->s = strdup(args[1]);
3934 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
3936 else if (!strcmp(args[0], "errorloc") ||
3937 !strcmp(args[0], "errorloc302") ||
3938 !strcmp(args[0], "errorloc303")) { /* error location */
3939 int errnum, errlen;
3940 char *err;
3941
Willy Tarreau977b8e42006-12-29 14:19:17 +01003942 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003944
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003946 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
3950
3951 errnum = atol(args[1]);
3952 if (!strcmp(args[0], "errorloc303")) {
3953 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3954 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3955 } else {
3956 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3957 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3958 }
3959
Willy Tarreau0f772532006-12-23 20:51:41 +01003960 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3961 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003962 chunk_destroy(&curproxy->errmsg[rc]);
3963 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003964 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003967
3968 if (rc >= HTTP_ERR_SIZE) {
3969 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3970 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 free(err);
3972 }
3973 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003974 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3975 int errnum, errlen, fd;
3976 char *err;
3977 struct stat stat;
3978
3979 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003981
3982 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003983 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003986 }
3987
3988 fd = open(args[2], O_RDONLY);
3989 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3990 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3991 file, linenum, args[2], args[1]);
3992 if (fd >= 0)
3993 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003996 }
3997
Willy Tarreau27a674e2009-08-17 07:23:33 +02003998 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003999 errlen = stat.st_size;
4000 } else {
4001 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004002 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004004 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004005 }
4006
4007 err = malloc(errlen); /* malloc() must succeed during parsing */
4008 errnum = read(fd, err, errlen);
4009 if (errnum != errlen) {
4010 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4011 file, linenum, args[2], args[1]);
4012 close(fd);
4013 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004016 }
4017 close(fd);
4018
4019 errnum = atol(args[1]);
4020 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4021 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004022 chunk_destroy(&curproxy->errmsg[rc]);
4023 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004024 break;
4025 }
4026 }
4027
4028 if (rc >= HTTP_ERR_SIZE) {
4029 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4030 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004032 free(err);
4033 }
4034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004036 struct cfg_kw_list *kwl;
4037 int index;
4038
4039 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4040 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4041 if (kwl->kw[index].section != CFG_LISTEN)
4042 continue;
4043 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4044 /* prepare error message just in case */
4045 snprintf(trash, sizeof(trash),
4046 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004047 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4048 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004049 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004052 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004053 else if (rc > 0) {
4054 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_WARN;
4056 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004057 }
Willy Tarreau93893792009-07-23 13:19:11 +02004058 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004059 }
4060 }
4061 }
4062
Willy Tarreau6daf3432008-01-22 16:44:08 +01004063 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 }
Willy Tarreau93893792009-07-23 13:19:11 +02004067 out:
4068 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069}
4070
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004071int
4072cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4073{
4074
4075 int err_code = 0;
4076 const char *err;
4077
4078 if (!strcmp(args[0], "userlist")) { /* new userlist */
4079 struct userlist *newul;
4080
4081 if (!*args[1]) {
4082 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4083 file, linenum, args[0]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087
4088 err = invalid_char(args[1]);
4089 if (err) {
4090 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4091 file, linenum, *err, args[0], args[1]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095
4096 for (newul = userlist; newul; newul = newul->next)
4097 if (!strcmp(newul->name, args[1])) {
4098 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4099 file, linenum, args[1]);
4100 err_code |= ERR_WARN;
4101 goto out;
4102 }
4103
4104 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4105 if (!newul) {
4106 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4107 err_code |= ERR_ALERT | ERR_ABORT;
4108 goto out;
4109 }
4110
4111 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4112 newul->name = strdup(args[1]);
4113
4114 if (!newul->groupusers | !newul->name) {
4115 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4116 err_code |= ERR_ALERT | ERR_ABORT;
4117 goto out;
4118 }
4119
4120 newul->next = userlist;
4121 userlist = newul;
4122
4123 } else if (!strcmp(args[0], "group")) { /* new group */
4124 int cur_arg, i;
4125 const char *err;
4126
4127 if (!*args[1]) {
4128 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4129 file, linenum, args[0]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133
4134 err = invalid_char(args[1]);
4135 if (err) {
4136 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4137 file, linenum, *err, args[0], args[1]);
4138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
4140 }
4141
4142 for(i = 0; i < userlist->grpcnt; i++)
4143 if (!strcmp(userlist->groups[i], args[1])) {
4144 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4145 file, linenum, args[1], userlist->name);
4146 err_code |= ERR_ALERT;
4147 goto out;
4148 }
4149
4150 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4151 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4152 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156
4157 cur_arg = 2;
4158
4159 while (*args[cur_arg]) {
4160 if (!strcmp(args[cur_arg], "users")) {
4161 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 continue;
4164 } else {
4165 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4166 file, linenum, args[0]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170 }
4171
4172 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4173 } else if (!strcmp(args[0], "user")) { /* new user */
4174 struct auth_users *newuser;
4175 int cur_arg;
4176
4177 if (!*args[1]) {
4178 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4179 file, linenum, args[0]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 }
4183
4184 for (newuser = userlist->users; newuser; newuser = newuser->next)
4185 if (!strcmp(newuser->user, args[1])) {
4186 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4187 file, linenum, args[1], userlist->name);
4188 err_code |= ERR_ALERT;
4189 goto out;
4190 }
4191
4192 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4193 if (!newuser) {
4194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4195 err_code |= ERR_ALERT | ERR_ABORT;
4196 goto out;
4197 }
4198
4199 newuser->user = strdup(args[1]);
4200
4201 newuser->next = userlist->users;
4202 userlist->users = newuser;
4203
4204 cur_arg = 2;
4205
4206 while (*args[cur_arg]) {
4207 if (!strcmp(args[cur_arg], "password")) {
4208#ifndef CONFIG_HAP_CRYPT
4209 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4210 file, linenum);
4211 err_code |= ERR_ALERT;
4212#endif
4213 newuser->pass = strdup(args[cur_arg + 1]);
4214 cur_arg += 2;
4215 continue;
4216 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4217 newuser->pass = strdup(args[cur_arg + 1]);
4218 newuser->flags |= AU_O_INSECURE;
4219 cur_arg += 2;
4220 continue;
4221 } else if (!strcmp(args[cur_arg], "groups")) {
4222 newuser->groups = strdup(args[cur_arg + 1]);
4223 cur_arg += 2;
4224 continue;
4225 } else {
4226 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4227 file, linenum, args[0]);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
4230 }
4231 }
4232 } else {
4233 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 }
4236
4237out:
4238 return err_code;
4239}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004240
4241/*
4242 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004243 * Returns the error code, 0 if OK, or any combination of :
4244 * - ERR_ABORT: must abort ASAP
4245 * - ERR_FATAL: we can continue parsing but not start the service
4246 * - ERR_WARN: a warning has been emitted
4247 * - ERR_ALERT: an alert has been emitted
4248 * Only the two first ones can stop processing, the two others are just
4249 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004251int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004253 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 FILE *f;
4255 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004257 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 if ((f=fopen(file,"r")) == NULL)
4260 return -1;
4261
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004262 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004263 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004264 char *end;
4265 char *args[MAX_LINE_ARGS + 1];
4266 char *line = thisline;
4267
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 linenum++;
4269
4270 end = line + strlen(line);
4271
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004272 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4273 /* Check if we reached the limit and the last char is not \n.
4274 * Watch out for the last line without the terminating '\n'!
4275 */
4276 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004277 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004279 }
4280
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004282 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 line++;
4284
4285 arg = 0;
4286 args[arg] = line;
4287
4288 while (*line && arg < MAX_LINE_ARGS) {
4289 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4290 * C equivalent value. Other combinations left unchanged (eg: \1).
4291 */
4292 if (*line == '\\') {
4293 int skip = 0;
4294 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4295 *line = line[1];
4296 skip = 1;
4297 }
4298 else if (line[1] == 'r') {
4299 *line = '\r';
4300 skip = 1;
4301 }
4302 else if (line[1] == 'n') {
4303 *line = '\n';
4304 skip = 1;
4305 }
4306 else if (line[1] == 't') {
4307 *line = '\t';
4308 skip = 1;
4309 }
4310 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004311 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 unsigned char hex1, hex2;
4313 hex1 = toupper(line[2]) - '0';
4314 hex2 = toupper(line[3]) - '0';
4315 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4316 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4317 *line = (hex1<<4) + hex2;
4318 skip = 3;
4319 }
4320 else {
4321 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004322 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 }
4324 }
4325 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004326 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 end -= skip;
4328 }
4329 line++;
4330 }
4331 else if (*line == '#' || *line == '\n' || *line == '\r') {
4332 /* end of string, end of loop */
4333 *line = 0;
4334 break;
4335 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004336 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004338 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004339 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 line++;
4341 args[++arg] = line;
4342 }
4343 else {
4344 line++;
4345 }
4346 }
4347
4348 /* empty line */
4349 if (!**args)
4350 continue;
4351
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004352 if (*line) {
4353 /* we had to stop due to too many args.
4354 * Let's terminate the string, print the offending part then cut the
4355 * last arg.
4356 */
4357 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4358 line++;
4359 *line = '\0';
4360
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004361 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004362 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004363 err_code |= ERR_ALERT | ERR_FATAL;
4364 args[arg] = line;
4365 }
4366
Willy Tarreau540abe42007-05-02 20:50:16 +02004367 /* zero out remaining args and ensure that at least one entry
4368 * is zeroed out.
4369 */
4370 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 args[arg] = line;
4372 }
4373
Willy Tarreau3842f002009-06-14 11:39:52 +02004374 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004375 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004376 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004377 for (arg=0; *args[arg+1]; arg++)
4378 args[arg] = args[arg+1]; // shift args after inversion
4379 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004380 else if (!strcmp(args[0], "default")) {
4381 kwm = KWM_DEF;
4382 for (arg=0; *args[arg+1]; arg++)
4383 args[arg] = args[arg+1]; // shift args after inversion
4384 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004385
Willy Tarreau3842f002009-06-14 11:39:52 +02004386 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4387 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004389 }
4390
Willy Tarreau977b8e42006-12-29 14:19:17 +01004391 if (!strcmp(args[0], "listen") ||
4392 !strcmp(args[0], "frontend") ||
4393 !strcmp(args[0], "backend") ||
4394 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004395 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004397 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004398 cursection = strdup(args[0]);
4399 }
4400 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004402 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004403 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004404 } else if (!strcmp(args[0], "userlist")) {
4405 confsect = CFG_USERLIST;
4406 free(cursection);
4407 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 /* else it's a section keyword */
4410
4411 switch (confsect) {
4412 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 break;
4415 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004416 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004418 case CFG_USERLIST:
4419 err_code |= cfg_parse_users(file, linenum, args, kwm);
4420 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004422 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004423 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004425
4426 if (err_code & ERR_ABORT)
4427 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004429 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004430 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004432 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004433}
4434
Willy Tarreaubb925012009-07-23 13:36:36 +02004435/*
4436 * Returns the error code, 0 if OK, or any combination of :
4437 * - ERR_ABORT: must abort ASAP
4438 * - ERR_FATAL: we can continue parsing but not start the service
4439 * - ERR_WARN: a warning has been emitted
4440 * - ERR_ALERT: an alert has been emitted
4441 * Only the two first ones can stop processing, the two others are just
4442 * indicators.
4443 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004444int check_config_validity()
4445{
4446 int cfgerr = 0;
4447 struct proxy *curproxy = NULL;
4448 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004449 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004450 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004451 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452
4453 /*
4454 * Now, check for the integrity of all that we have collected.
4455 */
4456
4457 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004458 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004460 /* first, we will invert the proxy list order */
4461 curproxy = NULL;
4462 while (proxy) {
4463 struct proxy *next;
4464
4465 next = proxy->next;
4466 proxy->next = curproxy;
4467 curproxy = proxy;
4468 if (!next)
4469 break;
4470 proxy = next;
4471 }
4472
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004474 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 }
4478
4479 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004480 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004481 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004482 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004483 unsigned int next_id;
4484
4485 if (!curproxy->uuid) {
4486 /* proxy ID not set, use automatic numbering with first
4487 * spare entry starting with next_pxid.
4488 */
4489 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4490 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4491 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4492 next_pxid++;
4493 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004494
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004496 /* ensure we don't keep listeners uselessly bound */
4497 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 curproxy = curproxy->next;
4499 continue;
4500 }
4501
Willy Tarreauff01a212009-03-15 13:46:16 +01004502 switch (curproxy->mode) {
4503 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004504 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004505 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004506 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004508 cfgerr++;
4509 }
4510
4511 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004512 Warning("config : servers will be ignored for %s '%s'.\n",
4513 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004514 break;
4515
4516 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004518 break;
4519
4520 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004521 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004522 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004523 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4524 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004525 cfgerr++;
4526 }
4527 break;
4528 }
4529
4530 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004531 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4532 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004533 cfgerr++;
4534 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004535
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004536 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004537 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004538 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004539 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4540 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004541 cfgerr++;
4542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004544 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004545 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4546 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004547 cfgerr++;
4548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004550 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004551 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4552 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004553 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004554 }
4555 }
4556 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4557 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4558 /* If no LB algo is set in a backend, and we're not in
4559 * transparent mode, dispatch mode nor proxy mode, we
4560 * want to use balance roundrobin by default.
4561 */
4562 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4563 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 }
4565 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004566
Willy Tarreau82936582007-11-30 15:20:09 +01004567 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4568 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004569 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4570 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004571 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004572 }
4573
Willy Tarreauef781042010-01-27 11:53:01 +01004574 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4575 curproxy->options &= ~PR_O2_CHK_SNDST;
4576 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4577 "send-state", proxy_type_str(curproxy), curproxy->id);
4578 err_code |= ERR_WARN;
4579 }
4580
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004581 /* if a default backend was specified, let's find it */
4582 if (curproxy->defbe.name) {
4583 struct proxy *target;
4584
Alex Williams96532db2009-11-01 21:27:13 -05004585 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004586 if (!target) {
4587 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4588 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004589 cfgerr++;
4590 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004591 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4592 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004593 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004594 } else {
4595 free(curproxy->defbe.name);
4596 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004597 /* we force the backend to be present on at least all of
4598 * the frontend's processes.
4599 */
4600 target->bind_proc = curproxy->bind_proc ?
4601 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
4603 }
4604
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004605 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004606 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4607 /* map jump target for ACT_SETBE in req_rep chain */
4608 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004609 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004610 struct proxy *target;
4611
Willy Tarreaua496b602006-12-17 23:15:24 +01004612 if (exp->action != ACT_SETBE)
4613 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004614
Alex Williams96532db2009-11-01 21:27:13 -05004615 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004616 if (!target) {
4617 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4618 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004619 cfgerr++;
4620 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004621 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4622 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004623 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004624 } else {
4625 free((void *)exp->replace);
4626 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004627 /* we force the backend to be present on at least all of
4628 * the frontend's processes.
4629 */
4630 target->bind_proc = curproxy->bind_proc ?
4631 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004632 }
4633 }
4634 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004635
4636 /* find the target proxy for 'use_backend' rules */
4637 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004638 struct proxy *target;
4639
Alex Williams96532db2009-11-01 21:27:13 -05004640 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004641
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004642 if (!target) {
4643 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4644 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004645 cfgerr++;
4646 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004647 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4648 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004649 cfgerr++;
4650 } else {
4651 free((void *)rule->be.name);
4652 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004653 /* we force the backend to be present on at least all of
4654 * the frontend's processes.
4655 */
4656 target->bind_proc = curproxy->bind_proc ?
4657 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004658 }
4659 }
4660
Emeric Brunb982a3d2010-01-04 15:45:53 +01004661 /* find the target table for 'stick' rules */
4662 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4663 struct proxy *target;
4664
Emeric Brun1d33b292010-01-04 15:47:17 +01004665 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4666 if (mrule->flags & STK_IS_STORE)
4667 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4668
Emeric Brunb982a3d2010-01-04 15:45:53 +01004669 if (mrule->table.name)
4670 target = findproxy(mrule->table.name, PR_CAP_BE);
4671 else
4672 target = curproxy;
4673
4674 if (!target) {
4675 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4676 curproxy->id, mrule->table.name);
4677 cfgerr++;
4678 }
4679 else if (target->table.size == 0) {
4680 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4681 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4682 cfgerr++;
4683 }
4684 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4685 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4686 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4687 cfgerr++;
4688 }
4689 else {
4690 free((void *)mrule->table.name);
4691 mrule->table.t = &(target->table);
4692 }
4693 }
4694
4695 /* find the target table for 'store response' rules */
4696 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4697 struct proxy *target;
4698
Emeric Brun1d33b292010-01-04 15:47:17 +01004699 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4700
Emeric Brunb982a3d2010-01-04 15:45:53 +01004701 if (mrule->table.name)
4702 target = findproxy(mrule->table.name, PR_CAP_BE);
4703 else
4704 target = curproxy;
4705
4706 if (!target) {
4707 Alert("Proxy '%s': unable to find store table '%s'.\n",
4708 curproxy->id, mrule->table.name);
4709 cfgerr++;
4710 }
4711 else if (target->table.size == 0) {
4712 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4713 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4714 cfgerr++;
4715 }
4716 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4717 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4718 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4719 cfgerr++;
4720 }
4721 else {
4722 free((void *)mrule->table.name);
4723 mrule->table.t = &(target->table);
4724 }
4725 }
4726
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004727 if (curproxy->uri_auth && !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
4728 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4729 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4730 "proxy", curproxy->id);
4731 cfgerr++;
4732 goto out_uri_auth_compat;
4733 }
4734
4735 if (curproxy->uri_auth && curproxy->uri_auth->userlist) {
4736 const char *uri_auth_compat_acl[3] = { ".internal-stats-auth-ok", "http_auth(.internal-stats-userlist)", ""};
4737 const char *uri_auth_compat_req[][4] = {
4738 { "allow", "if", ".internal-stats-auth-ok", ""},
4739 { "auth", "", "", ""},
4740 { 0 },
4741 };
4742 struct req_acl_rule *req_acl;
4743 int i;
4744
4745 if (parse_acl(uri_auth_compat_acl, &curproxy->acl) == NULL) {
4746 Alert("Error compiling internal auth-compat acl.\n");
4747 cfgerr++;
4748 goto out_uri_auth_compat;
4749 }
4750
4751 if (curproxy->uri_auth->auth_realm) {
4752 uri_auth_compat_req[1][1] = "realm";
4753 uri_auth_compat_req[1][2] = curproxy->uri_auth->auth_realm;
4754 } else
4755 uri_auth_compat_req[1][1] = "";
4756
4757 for (i = 0; *uri_auth_compat_req[i]; i++) {
Willy Tarreau9cc670f2010-02-01 10:43:44 +01004758 req_acl = parse_auth_cond(uri_auth_compat_req[i], "internal-stats-auth-compat", i, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004759 if (!req_acl) {
4760 cfgerr++;
4761 break;
4762 }
4763
4764 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4765 }
4766
4767 if (curproxy->uri_auth->auth_realm) {
4768 free(curproxy->uri_auth->auth_realm);
4769 curproxy->uri_auth->auth_realm = NULL;
4770 }
4771
4772 }
4773out_uri_auth_compat:
4774
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004775 cfgerr += acl_find_targets(curproxy);
4776
Willy Tarreau2738a142006-07-08 17:28:09 +02004777 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004778 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004779 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004780 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004781 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004782 " | While not properly invalid, you will certainly encounter various problems\n"
4783 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004784 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004785 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004786 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004787 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004788
Willy Tarreau1fa31262007-12-03 00:36:16 +01004789 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4790 * We must still support older configurations, so let's find out whether those
4791 * parameters have been set or must be copied from contimeouts.
4792 */
4793 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004794 if (!curproxy->timeout.tarpit ||
4795 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004796 /* tarpit timeout not set. We search in the following order:
4797 * default.tarpit, curr.connect, default.connect.
4798 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004799 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004800 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004801 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004802 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004803 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004804 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004805 }
4806 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004807 (!curproxy->timeout.queue ||
4808 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004809 /* queue timeout not set. We search in the following order:
4810 * default.queue, curr.connect, default.connect.
4811 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004812 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004813 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004814 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004815 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004816 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004817 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004818 }
4819 }
4820
Willy Tarreauf3c69202006-07-09 16:42:34 +02004821 if (curproxy->options & PR_O_SSL3_CHK) {
4822 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4823 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4824 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4825 }
4826
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004827 /* The small pools required for the capture lists */
4828 if (curproxy->nb_req_cap)
4829 curproxy->req_cap_pool = create_pool("ptrcap",
4830 curproxy->nb_req_cap * sizeof(char *),
4831 MEM_F_SHARED);
4832 if (curproxy->nb_rsp_cap)
4833 curproxy->rsp_cap_pool = create_pool("ptrcap",
4834 curproxy->nb_rsp_cap * sizeof(char *),
4835 MEM_F_SHARED);
4836
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004837 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4838 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4839 MEM_F_SHARED);
4840
Willy Tarreau86034312006-12-29 00:10:33 +01004841 /* for backwards compatibility with "listen" instances, if
4842 * fullconn is not set but maxconn is set, then maxconn
4843 * is used.
4844 */
4845 if (!curproxy->fullconn)
4846 curproxy->fullconn = curproxy->maxconn;
4847
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 /* first, we will invert the servers list order */
4849 newsrv = NULL;
4850 while (curproxy->srv) {
4851 struct server *next;
4852
4853 next = curproxy->srv->next;
4854 curproxy->srv->next = newsrv;
4855 newsrv = curproxy->srv;
4856 if (!next)
4857 break;
4858 curproxy->srv = next;
4859 }
4860
Willy Tarreau20697042007-11-15 23:26:18 +01004861 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004862 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004864 /* We have to initialize the server lookup mechanism depending
4865 * on what LB algorithm was choosen.
4866 */
4867
4868 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4869 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4870 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004871 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4872 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4873 init_server_map(curproxy);
4874 } else {
4875 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4876 fwrr_init_server_groups(curproxy);
4877 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004878 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004879
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004880 case BE_LB_KIND_LC:
4881 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004882 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004883 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004884
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004885 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004886 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4887 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4888 chash_init_server_tree(curproxy);
4889 } else {
4890 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4891 init_server_map(curproxy);
4892 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004893 break;
4894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895
4896 if (curproxy->options & PR_O_LOGASAP)
4897 curproxy->to_log &= ~LW_BYTES;
4898
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004899 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4900 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4901 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4902 proxy_type_str(curproxy), curproxy->id);
4903 err_code |= ERR_WARN;
4904 }
4905
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004907 * ensure that we're not cross-dressing a TCP server into HTTP.
4908 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004909 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004910 newsrv = curproxy->srv;
4911 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004912 if (!newsrv->puid) {
4913 /* server ID not set, use automatic numbering with first
4914 * spare entry starting with next_svid.
4915 */
4916 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4917 newsrv->conf.id.key = newsrv->puid = next_id;
4918 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4919 next_id++;
4920 }
4921
Willy Tarreau21d2af32008-02-14 20:25:24 +01004922 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004923 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4924 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004925 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004926 }
4927 newsrv = newsrv->next;
4928 }
4929
4930 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 * If this server supports a maxconn parameter, it needs a dedicated
4932 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004933 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 */
4935 newsrv = curproxy->srv;
4936 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004937 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 /* Only 'minconn' was specified, or it was higher than or equal
4939 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4940 * this will avoid further useless expensive computations.
4941 */
4942 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004943 } else if (newsrv->maxconn && !newsrv->minconn) {
4944 /* minconn was not specified, so we set it to maxconn */
4945 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004946 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004947 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4948 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004949 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004952 if (newsrv->trackit) {
4953 struct proxy *px;
4954 struct server *srv;
4955 char *pname, *sname;
4956
4957 pname = newsrv->trackit;
4958 sname = strrchr(pname, '/');
4959
4960 if (sname)
4961 *sname++ = '\0';
4962 else {
4963 sname = pname;
4964 pname = NULL;
4965 }
4966
4967 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004968 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004969 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004970 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4971 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004972 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004973 cfgerr++;
4974 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004975 }
4976 } else
4977 px = curproxy;
4978
4979 srv = findserver(px, sname);
4980 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004981 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4982 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004983 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004984 cfgerr++;
4985 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004986 }
4987
4988 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004989 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004990 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004991 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004992 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004993 cfgerr++;
4994 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004995 }
4996
4997 if (curproxy != px &&
4998 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004999 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005000 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005001 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005002 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005003 cfgerr++;
5004 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005005 }
5006
5007 newsrv->tracked = srv;
5008 newsrv->tracknext = srv->tracknext;
5009 srv->tracknext = newsrv;
5010
5011 free(newsrv->trackit);
5012 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005013 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 newsrv = newsrv->next;
5015 }
5016
Willy Tarreauc1a21672009-08-16 22:37:44 +02005017 if (curproxy->cap & PR_CAP_FE) {
5018 if (curproxy->tcp_req.inspect_delay ||
5019 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5020 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5021
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005022 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005023 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005024 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005025 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005026
5027 /* both TCP and HTTP must check switching rules */
5028 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5029 }
5030
5031 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005032 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005033 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005034 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005035 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005036
Emeric Brunb982a3d2010-01-04 15:45:53 +01005037 /* init table on backend capabilities proxy */
5038 stktable_init(&curproxy->table);
5039
Willy Tarreauc1a21672009-08-16 22:37:44 +02005040 /* If the backend does requires RDP cookie persistence, we have to
5041 * enable the corresponding analyser.
5042 */
5043 if (curproxy->options2 & PR_O2_RDPC_PRST)
5044 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5045 }
5046
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005047 listener = NULL;
5048 while (curproxy->listen) {
5049 struct listener *next;
5050
5051 next = curproxy->listen->next;
5052 curproxy->listen->next = listener;
5053 listener = curproxy->listen;
5054
5055 if (!next)
5056 break;
5057
5058 curproxy->listen = next;
5059 }
5060
Willy Tarreaue6b98942007-10-29 01:09:36 +01005061 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005062 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005063 listener = curproxy->listen;
5064 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005065 if (!listener->luid) {
5066 /* listener ID not set, use automatic numbering with first
5067 * spare entry starting with next_luid.
5068 */
5069 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5070 listener->conf.id.key = listener->luid = next_id;
5071 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
5072 next_id++;
5073 }
5074
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005075 /* enable separate counters */
5076 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5077 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5078 if (!listener->name) {
5079 sprintf(trash, "sock-%d", listener->luid);
5080 listener->name = strdup(trash);
5081 }
5082 }
5083
Willy Tarreaue6b98942007-10-29 01:09:36 +01005084 if (curproxy->options & PR_O_TCP_NOLING)
5085 listener->options |= LI_O_NOLINGER;
5086 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005087 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005088 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005089 listener->accept = event_accept;
5090 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005091 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005092 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005093
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005094 /* smart accept mode is automatic in HTTP mode */
5095 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5096 (curproxy->mode == PR_MODE_HTTP &&
5097 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5098 listener->options |= LI_O_NOQUICKACK;
5099
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005100 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005101 listener = listener->next;
5102 }
5103
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 curproxy = curproxy->next;
5105 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005106
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005107 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5108 struct auth_users *curuser;
5109 int g;
5110
5111 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5112 unsigned int group_mask = 0;
5113 char *group = NULL;
5114
5115 if (!curuser->groups)
5116 continue;
5117
5118 while ((group = strtok(group?NULL:curuser->groups, ","))) {
5119
5120 for (g = 0; g < curuserlist->grpcnt; g++)
5121 if (!strcmp(curuserlist->groups[g], group))
5122 break;
5123
5124 if (g == curuserlist->grpcnt) {
5125 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5126 curuserlist->name, group, curuser->user);
5127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
5129 }
5130
5131 group_mask |= (1 << g);
5132 }
5133
5134 free(curuser->groups);
5135 curuser->group_mask = group_mask;
5136 }
5137
5138 for (g = 0; g < curuserlist->grpcnt; g++) {
5139 char *user = NULL;
5140
5141 if (!curuserlist->groupusers[g])
5142 continue;
5143
5144 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5145 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5146 if (!strcmp(curuser->user, user))
5147 break;
5148
5149 if (!curuser) {
5150 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5151 curuserlist->name, user, curuserlist->groups[g]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155
5156 curuser->group_mask |= (1 << g);
5157 }
5158
5159 free(curuserlist->groupusers[g]);
5160 }
5161
5162 free(curuserlist->groupusers);
5163
5164#ifdef DEBUG_AUTH
5165 for (g = 0; g < curuserlist->grpcnt; g++) {
5166 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5167
5168 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5169 if (curuser->group_mask & (1 << g))
5170 fprintf(stderr, " %s", curuser->user);
5171 }
5172
5173 fprintf(stderr, "\n");
5174 }
5175#endif
5176
5177 }
5178
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005179 /*
5180 * Recount currently required checks.
5181 */
5182
5183 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5184 int optnum;
5185
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005186 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5187 if (curproxy->options & cfg_opts[optnum].val)
5188 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005189
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005190 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5191 if (curproxy->options2 & cfg_opts2[optnum].val)
5192 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005193 }
5194
Willy Tarreaubb925012009-07-23 13:36:36 +02005195 if (cfgerr > 0)
5196 err_code |= ERR_ALERT | ERR_FATAL;
5197 out:
5198 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199}
5200
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005201/*
5202 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5203 * parsing sessions.
5204 */
5205void cfg_register_keywords(struct cfg_kw_list *kwl)
5206{
5207 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5208}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005210/*
5211 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5212 */
5213void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5214{
5215 LIST_DEL(&kwl->list);
5216 LIST_INIT(&kwl->list);
5217}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218
5219/*
5220 * Local variables:
5221 * c-indent-level: 8
5222 * c-basic-offset: 8
5223 * End:
5224 */