blob: 5c181f16c4ffff9af06a657a327c57f8d9063f43 [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);
885 LIST_INIT(&p->block_cond);
886 LIST_INIT(&p->redirect_rules);
887 LIST_INIT(&p->mon_fail_cond);
888 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100889 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100890 LIST_INIT(&p->sticking_rules);
891 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100892 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100893 LIST_INIT(&p->req_add);
894 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100895
896 /* Timeouts are defined as -1 */
897 proxy_reset_timeouts(p);
898}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200900void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100902 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 defproxy.mode = PR_MODE_TCP;
904 defproxy.state = PR_STNEW;
905 defproxy.maxconn = cfg_maxpconn;
906 defproxy.conn_retries = CONN_RETRIES;
907 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100908
909 defproxy.defsrv.inter = DEF_CHKINTR;
910 defproxy.defsrv.fastinter = 0;
911 defproxy.defsrv.downinter = 0;
912 defproxy.defsrv.rise = DEF_RISETIME;
913 defproxy.defsrv.fall = DEF_FALLTIME;
914 defproxy.defsrv.check_port = 0;
915 defproxy.defsrv.maxqueue = 0;
916 defproxy.defsrv.minconn = 0;
917 defproxy.defsrv.maxconn = 0;
918 defproxy.defsrv.slowstart = 0;
919 defproxy.defsrv.onerror = DEF_HANA_ONERR;
920 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
921 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922}
923
Willy Tarreauade5ec42010-01-28 19:33:49 +0100924
925static int create_cond_regex_rule(const char *file, int line,
926 struct proxy *px, int dir, int action, int flags,
927 const char *cmd, const char *reg, const char *repl,
928 const char **cond_start)
929{
930 regex_t *preg = NULL;
931 const char *err;
932 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100933 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100934
935 if (px == &defproxy) {
936 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto err;
939 }
940
941 if (*reg == 0) {
942 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto err;
945 }
946
947 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
948 err_code |= ERR_WARN;
949
Willy Tarreau5321c422010-01-28 20:35:13 +0100950 if (cond_start &&
951 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
952 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
953 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
954 file, line, cmd);
955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto err;
957 }
958 }
959 else if (cond_start && **cond_start) {
960 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
961 file, line, cmd, *cond_start);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto err;
964 }
965
966 if (dir == ACL_DIR_REQ)
967 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100968 else
969 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100970
Willy Tarreauade5ec42010-01-28 19:33:49 +0100971 preg = calloc(1, sizeof(regex_t));
972 if (!preg) {
973 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
974 err_code = ERR_ALERT | ERR_FATAL;
975 goto err;
976 }
977
978 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
979 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
980 err_code = ERR_ALERT | ERR_FATAL;
981 goto err;
982 }
983
984 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100985 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +0100986 if (repl && err) {
987 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
988 file, line, cmd, *err);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto err;
991 }
992
993 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
994 err_code |= ERR_WARN;
995
996 return err_code;
997 err:
998 free(preg);
999 return err_code;
1000}
1001
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001004 * Returns the error code, 0 if OK, or any combination of :
1005 * - ERR_ABORT: must abort ASAP
1006 * - ERR_FATAL: we can continue parsing but not start the service
1007 * - ERR_WARN: a warning has been emitted
1008 * - ERR_ALERT: an alert has been emitted
1009 * Only the two first ones can stop processing, the two others are just
1010 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001012int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013{
1014 static struct proxy *curproxy = NULL;
1015 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001016 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001017 int rc;
1018 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001019 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001020 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 if (!strcmp(args[0], "listen"))
1023 rc = PR_CAP_LISTEN;
1024 else if (!strcmp(args[0], "frontend"))
1025 rc = PR_CAP_FE | PR_CAP_RS;
1026 else if (!strcmp(args[0], "backend"))
1027 rc = PR_CAP_BE | PR_CAP_RS;
1028 else if (!strcmp(args[0], "ruleset"))
1029 rc = PR_CAP_RS;
1030 else
1031 rc = PR_CAP_NONE;
1032
1033 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 if (!*args[1]) {
1035 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1036 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001038 err_code |= ERR_ALERT | ERR_ABORT;
1039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001040 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001041
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001042 err = invalid_char(args[1]);
1043 if (err) {
1044 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1045 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001047 }
1048
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001049 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1050 /*
1051 * If there are two proxies with the same name only following
1052 * combinations are allowed:
1053 *
1054 * listen backend frontend ruleset
1055 * listen - - - -
1056 * backend - - OK -
1057 * frontend - OK - -
1058 * ruleset - - - -
1059 */
1060
1061 if (!strcmp(curproxy->id, args[1]) &&
1062 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1063 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001064 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1065 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1066 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001067 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001068 }
1069 }
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001073 err_code |= ERR_ALERT | ERR_ABORT;
1074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001076
Willy Tarreau97cb7802010-01-03 20:23:58 +01001077 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 curproxy->next = proxy;
1079 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001080 curproxy->conf.file = file;
1081 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001082 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001084 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085
1086 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001087 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001088 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001089 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001090 err_code |= ERR_FATAL;
1091 goto out;
1092 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001093 new = curproxy->listen;
1094 while (new != last) {
1095 new->conf.file = file;
1096 new->conf.line = linenum;
1097 new = new->next;
1098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 global.maxsock++;
1100 }
1101
1102 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001103 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1104
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001107 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001108 curproxy->no_options = defproxy.no_options;
1109 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001110 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001111 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001112 curproxy->except_net = defproxy.except_net;
1113 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001114 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001115 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001117 if (defproxy.fwdfor_hdr_len) {
1118 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1119 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1120 }
1121
Willy Tarreaub86db342009-11-30 11:50:16 +01001122 if (defproxy.orgto_hdr_len) {
1123 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1124 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1125 }
1126
Willy Tarreau977b8e42006-12-29 14:19:17 +01001127 if (curproxy->cap & PR_CAP_FE) {
1128 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001129 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001130 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001131
1132 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001133 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1134 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001135
1136 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138
Willy Tarreau977b8e42006-12-29 14:19:17 +01001139 if (curproxy->cap & PR_CAP_BE) {
1140 curproxy->fullconn = defproxy.fullconn;
1141 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001142
Willy Tarreau977b8e42006-12-29 14:19:17 +01001143 if (defproxy.check_req)
1144 curproxy->check_req = strdup(defproxy.check_req);
1145 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147 if (defproxy.cookie_name)
1148 curproxy->cookie_name = strdup(defproxy.cookie_name);
1149 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001150 if (defproxy.cookie_domain)
1151 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001152
Emeric Brun647caf12009-06-30 17:57:00 +02001153 if (defproxy.rdp_cookie_name)
1154 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1155 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1156
Willy Tarreau01732802007-11-01 22:48:15 +01001157 if (defproxy.url_param_name)
1158 curproxy->url_param_name = strdup(defproxy.url_param_name);
1159 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001160
Benoitaffb4812009-03-25 13:02:10 +01001161 if (defproxy.hh_name)
1162 curproxy->hh_name = strdup(defproxy.hh_name);
1163 curproxy->hh_len = defproxy.hh_len;
1164 curproxy->hh_match_domain = defproxy.hh_match_domain;
1165
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001166 if (defproxy.iface_name)
1167 curproxy->iface_name = strdup(defproxy.iface_name);
1168 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001171 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001172 if (defproxy.capture_name)
1173 curproxy->capture_name = strdup(defproxy.capture_name);
1174 curproxy->capture_namelen = defproxy.capture_namelen;
1175 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177
Willy Tarreau977b8e42006-12-29 14:19:17 +01001178 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001179 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001180 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001181 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001182 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 curproxy->uri_auth = defproxy.uri_auth;
1184 curproxy->mon_net = defproxy.mon_net;
1185 curproxy->mon_mask = defproxy.mon_mask;
1186 if (defproxy.monitor_uri)
1187 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1188 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001189 if (defproxy.defbe.name)
1190 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001191 }
1192
1193 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001194 curproxy->timeout.connect = defproxy.timeout.connect;
1195 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001196 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001197 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001198 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001199 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001200 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 curproxy->source_addr = defproxy.source_addr;
1202 }
1203
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 curproxy->mode = defproxy.mode;
1205 curproxy->logfac1 = defproxy.logfac1;
1206 curproxy->logsrv1 = defproxy.logsrv1;
1207 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001208 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 curproxy->logfac2 = defproxy.logfac2;
1210 curproxy->logsrv2 = defproxy.logsrv2;
1211 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001212 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001214 curproxy->conf.used_listener_id = EB_ROOT;
1215 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001216
Willy Tarreau93893792009-07-23 13:19:11 +02001217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 }
1219 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1220 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001221 /* FIXME-20070101: we should do this too at the end of the
1222 * config parsing to free all default values.
1223 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001224 free(defproxy.check_req);
1225 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001226 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001227 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001228 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001229 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001230 free(defproxy.capture_name);
1231 free(defproxy.monitor_uri);
1232 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001233 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001234 free(defproxy.fwdfor_hdr_name);
1235 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001236 free(defproxy.orgto_hdr_name);
1237 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001238
Willy Tarreaua534fea2008-08-03 12:19:50 +02001239 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001240 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001241
Willy Tarreaubaaee002006-06-26 02:48:02 +02001242 /* we cannot free uri_auth because it might already be used */
1243 init_default_instance();
1244 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001245 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001247 }
1248 else if (curproxy == NULL) {
1249 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 }
1253
Willy Tarreau977b8e42006-12-29 14:19:17 +01001254
1255 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001257 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001258 int cur_arg;
1259
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 if (curproxy == &defproxy) {
1261 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001265 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001266 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267
1268 if (strchr(args[1], ':') == NULL) {
1269 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001274
1275 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001276 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001280
Willy Tarreau90a570f2009-10-04 20:54:54 +02001281 new_listen = curproxy->listen;
1282 while (new_listen != last_listen) {
1283 new_listen->conf.file = file;
1284 new_listen->conf.line = linenum;
1285 new_listen = new_listen->next;
1286 }
1287
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001288 cur_arg = 2;
1289 while (*(args[cur_arg])) {
1290 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1291#ifdef SO_BINDTODEVICE
1292 struct listener *l;
1293
1294 if (!*args[cur_arg + 1]) {
1295 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001299 }
1300
1301 for (l = curproxy->listen; l != last_listen; l = l->next)
1302 l->interface = strdup(args[cur_arg + 1]);
1303
1304 global.last_checks |= LSTCHK_NETADM;
1305
1306 cur_arg += 2;
1307 continue;
1308#else
1309 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1310 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001313#endif
1314 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001315 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1316#ifdef TCP_MAXSEG
1317 struct listener *l;
1318 int mss;
1319
1320 if (!*args[cur_arg + 1]) {
1321 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1322 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001325 }
1326
1327 mss = str2uic(args[cur_arg + 1]);
1328 if (mss < 1 || mss > 65535) {
1329 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001333 }
1334
1335 for (l = curproxy->listen; l != last_listen; l = l->next)
1336 l->maxseg = mss;
1337
1338 cur_arg += 2;
1339 continue;
1340#else
1341 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1342 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001345#endif
1346 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001347
1348 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1349#ifdef TCP_DEFER_ACCEPT
1350 struct listener *l;
1351
1352 for (l = curproxy->listen; l != last_listen; l = l->next)
1353 l->options |= LI_O_DEF_ACCEPT;
1354
1355 cur_arg ++;
1356 continue;
1357#else
1358 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1359 file, linenum, args[0], args[cur_arg]);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto out;
1362#endif
1363 }
1364
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001365 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001366#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001367 struct listener *l;
1368
1369 for (l = curproxy->listen; l != last_listen; l = l->next)
1370 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001371
1372 cur_arg ++;
1373 continue;
1374#else
1375 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1376 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001379#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001380 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001381
1382 if (!strcmp(args[cur_arg], "name")) {
1383 struct listener *l;
1384
1385 for (l = curproxy->listen; l != last_listen; l = l->next)
1386 l->name = strdup(args[cur_arg + 1]);
1387
1388 cur_arg += 2;
1389 continue;
1390 }
1391
1392 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001393 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001394 struct listener *l;
1395
1396 if (curproxy->listen->next != last_listen) {
1397 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1398 file, linenum, args[cur_arg]);
1399 err_code |= ERR_ALERT | ERR_FATAL;
1400 goto out;
1401 }
1402
1403 if (!*args[cur_arg + 1]) {
1404 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1405 file, linenum, args[cur_arg]);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto out;
1408 }
1409
1410 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001411 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001412
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001413 if (curproxy->listen->luid <= 0) {
1414 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001415 file, linenum);
1416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
1418 }
1419
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001420 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1421 if (node) {
1422 l = container_of(node, struct listener, conf.id);
1423 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1424 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto out;
1427 }
1428 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1429
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001430 cur_arg += 2;
1431 continue;
1432 }
1433
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001434 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 +01001435 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
1437 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 }
1442 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1443 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1444 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001449 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001450 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001451
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 /* flush useless bits */
1453 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001456 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001457 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001458 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459
Willy Tarreau1c47f852006-07-09 08:22:27 +02001460 if (!*args[1]) {
1461 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1462 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001463 err_code |= ERR_ALERT | ERR_FATAL;
1464 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001465 }
1466
Willy Tarreaua534fea2008-08-03 12:19:50 +02001467 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001468 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001469 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001470 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001471 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1472
Willy Tarreau93893792009-07-23 13:19:11 +02001473 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1476 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1477 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1478 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1479 else {
1480 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 }
1484 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001485 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001486 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001487
1488 if (curproxy == &defproxy) {
1489 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1490 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001491 err_code |= ERR_ALERT | ERR_FATAL;
1492 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001493 }
1494
1495 if (!*args[1]) {
1496 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001500 }
1501
1502 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001503 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001504
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001505 if (curproxy->uuid <= 0) {
1506 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001510 }
1511
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001512 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1513 if (node) {
1514 struct proxy *target = container_of(node, struct proxy, conf.id);
1515 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1516 file, linenum, proxy_type_str(curproxy), curproxy->id,
1517 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001523 else if (!strcmp(args[0], "description")) {
1524 int i, len=0;
1525 char *d;
1526
Cyril Bonté99ed3272010-01-24 23:29:44 +01001527 if (curproxy == &defproxy) {
1528 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1529 file, linenum, args[0]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001534 if (!*args[1]) {
1535 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1536 file, linenum, args[0]);
1537 return -1;
1538 }
1539
1540 for(i=1; *args[i]; i++)
1541 len += strlen(args[i])+1;
1542
1543 d = (char *)calloc(1, len);
1544 curproxy->desc = d;
1545
1546 d += sprintf(d, "%s", args[1]);
1547 for(i=2; *args[i]; i++)
1548 d += sprintf(d, " %s", args[i]);
1549
1550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1552 curproxy->state = PR_STSTOPPED;
1553 }
1554 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1555 curproxy->state = PR_STNEW;
1556 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001557 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1558 int cur_arg = 1;
1559 unsigned int set = 0;
1560
1561 while (*args[cur_arg]) {
1562 int u;
1563 if (strcmp(args[cur_arg], "all") == 0) {
1564 set = 0;
1565 break;
1566 }
1567 else if (strcmp(args[cur_arg], "odd") == 0) {
1568 set |= 0x55555555;
1569 }
1570 else if (strcmp(args[cur_arg], "even") == 0) {
1571 set |= 0xAAAAAAAA;
1572 }
1573 else {
1574 u = str2uic(args[cur_arg]);
1575 if (u < 1 || u > 32) {
1576 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001578 err_code |= ERR_ALERT | ERR_FATAL;
1579 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001580 }
1581 if (u > global.nbproc) {
1582 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001585 }
1586 set |= 1 << (u - 1);
1587 }
1588 cur_arg++;
1589 }
1590 curproxy->bind_proc = set;
1591 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001592 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001593 if (curproxy == &defproxy) {
1594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001597 }
1598
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001599 err = invalid_char(args[1]);
1600 if (err) {
1601 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1602 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001604 }
1605
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001606 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1607 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1608 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001609 err_code |= ERR_ALERT | ERR_FATAL;
1610 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001611 }
1612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1614 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615
Willy Tarreau977b8e42006-12-29 14:19:17 +01001616 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001617 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001618
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 if (*(args[1]) == 0) {
1620 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1621 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001622 err_code |= ERR_ALERT | ERR_FATAL;
1623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001625
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001626 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001627 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 curproxy->cookie_name = strdup(args[1]);
1629 curproxy->cookie_len = strlen(curproxy->cookie_name);
1630
1631 cur_arg = 2;
1632 while (*(args[cur_arg])) {
1633 if (!strcmp(args[cur_arg], "rewrite")) {
1634 curproxy->options |= PR_O_COOK_RW;
1635 }
1636 else if (!strcmp(args[cur_arg], "indirect")) {
1637 curproxy->options |= PR_O_COOK_IND;
1638 }
1639 else if (!strcmp(args[cur_arg], "insert")) {
1640 curproxy->options |= PR_O_COOK_INS;
1641 }
1642 else if (!strcmp(args[cur_arg], "nocache")) {
1643 curproxy->options |= PR_O_COOK_NOC;
1644 }
1645 else if (!strcmp(args[cur_arg], "postonly")) {
1646 curproxy->options |= PR_O_COOK_POST;
1647 }
1648 else if (!strcmp(args[cur_arg], "prefix")) {
1649 curproxy->options |= PR_O_COOK_PFX;
1650 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001651 else if (!strcmp(args[cur_arg], "domain")) {
1652 if (!*args[cur_arg + 1]) {
1653 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1654 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001657 }
1658
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001659 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001660 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001661 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1662 " dots nor does not start with a dot."
1663 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001664 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001665 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001666 }
1667
1668 err = invalid_domainchar(args[cur_arg + 1]);
1669 if (err) {
1670 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1671 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001674 }
1675
Willy Tarreau68a897b2009-12-03 23:28:34 +01001676 if (!curproxy->cookie_domain) {
1677 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1678 } else {
1679 /* one domain was already specified, add another one by
1680 * building the string which will be returned along with
1681 * the cookie.
1682 */
1683 char *new_ptr;
1684 int new_len = strlen(curproxy->cookie_domain) +
1685 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1686 new_ptr = malloc(new_len);
1687 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1688 free(curproxy->cookie_domain);
1689 curproxy->cookie_domain = new_ptr;
1690 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001691 cur_arg++;
1692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001694 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001695 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 }
1699 cur_arg++;
1700 }
1701 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1702 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1703 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 }
1706
1707 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1708 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1709 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 }
1712 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001713 else if (!strcmp(args[0], "persist")) { /* persist */
1714 if (*(args[1]) == 0) {
1715 Alert("parsing [%s:%d] : missing persist method.\n",
1716 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001719 }
1720
1721 if (!strncmp(args[1], "rdp-cookie", 10)) {
1722 curproxy->options2 |= PR_O2_RDPC_PRST;
1723
Emeric Brunb982a3d2010-01-04 15:45:53 +01001724 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001725 const char *beg, *end;
1726
1727 beg = args[1] + 11;
1728 end = strchr(beg, ')');
1729
1730 if (!end || end == beg) {
1731 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1732 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001735 }
1736
1737 free(curproxy->rdp_cookie_name);
1738 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1739 curproxy->rdp_cookie_len = end-beg;
1740 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001741 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001742 free(curproxy->rdp_cookie_name);
1743 curproxy->rdp_cookie_name = strdup("msts");
1744 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1745 }
1746 else { /* syntax */
1747 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1748 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001751 }
1752 }
1753 else {
1754 Alert("parsing [%s:%d] : unknown persist method.\n",
1755 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001758 }
1759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001761 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001763 if (curproxy == &defproxy) {
1764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767 }
1768
Willy Tarreau977b8e42006-12-29 14:19:17 +01001769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001771
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001773 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 }
1778 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001779 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 curproxy->appsession_name = strdup(args[1]);
1781 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1782 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001783 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1784 if (err) {
1785 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1786 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001789 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001790 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001791
Willy Tarreau51041c72007-09-09 21:56:53 +02001792 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1793 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001794 err_code |= ERR_ALERT | ERR_ABORT;
1795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001797
1798 cur_arg = 6;
1799 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001800 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1801 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001802 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001803 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001804 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001805 } else if (!strcmp(args[cur_arg], "prefix")) {
1806 curproxy->options2 |= PR_O2_AS_PFX;
1807 } else if (!strcmp(args[cur_arg], "mode")) {
1808 if (!*args[cur_arg + 1]) {
1809 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1810 file, linenum, args[0], args[cur_arg]);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814
1815 cur_arg++;
1816 if (!strcmp(args[cur_arg], "query-string")) {
1817 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1818 curproxy->options2 |= PR_O2_AS_M_QS;
1819 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1820 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1821 curproxy->options2 |= PR_O2_AS_M_PP;
1822 } else {
1823 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001828 cur_arg++;
1829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830 } /* Url App Session */
1831 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001832 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001833 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001836 if (curproxy == &defproxy) {
1837 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 if (*(args[4]) == 0) {
1843 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001848 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 curproxy->capture_name = strdup(args[2]);
1850 curproxy->capture_namelen = strlen(curproxy->capture_name);
1851 curproxy->capture_len = atol(args[4]);
1852 if (curproxy->capture_len >= CAPTURE_LEN) {
1853 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1854 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001855 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856 curproxy->capture_len = CAPTURE_LEN - 1;
1857 }
1858 curproxy->to_log |= LW_COOKIE;
1859 }
1860 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1861 struct cap_hdr *hdr;
1862
1863 if (curproxy == &defproxy) {
1864 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 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 }
1868
1869 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1870 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1871 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 }
1875
1876 hdr = calloc(sizeof(struct cap_hdr), 1);
1877 hdr->next = curproxy->req_cap;
1878 hdr->name = strdup(args[3]);
1879 hdr->namelen = strlen(args[3]);
1880 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001881 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 hdr->index = curproxy->nb_req_cap++;
1883 curproxy->req_cap = hdr;
1884 curproxy->to_log |= LW_REQHDR;
1885 }
1886 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1887 struct cap_hdr *hdr;
1888
1889 if (curproxy == &defproxy) {
1890 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 +02001891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 }
1894
1895 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1896 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1897 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 }
1901 hdr = calloc(sizeof(struct cap_hdr), 1);
1902 hdr->next = curproxy->rsp_cap;
1903 hdr->name = strdup(args[3]);
1904 hdr->namelen = strlen(args[3]);
1905 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001906 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 hdr->index = curproxy->nb_rsp_cap++;
1908 curproxy->rsp_cap = hdr;
1909 curproxy->to_log |= LW_RSPHDR;
1910 }
1911 else {
1912 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1913 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
1915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
1917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 if (*(args[1]) == 0) {
1923 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1924 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_ALERT | ERR_FATAL;
1926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
1928 curproxy->conn_retries = atol(args[1]);
1929 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001930 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001931 if (curproxy == &defproxy) {
1932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001935 }
1936
Willy Tarreauef6494c2010-01-28 17:12:36 +01001937 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001938 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001942 }
1943
Willy Tarreauef6494c2010-01-28 17:12:36 +01001944 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001945 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1946 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001949 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001950
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001951 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001952 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001953 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001954 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001955 struct redirect_rule *rule;
1956 int cur_arg;
1957 int type = REDIRECT_TYPE_NONE;
1958 int code = 302;
1959 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001960 char *cookie = NULL;
1961 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001962 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001963
Cyril Bonté99ed3272010-01-24 23:29:44 +01001964 if (curproxy == &defproxy) {
1965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
1968 }
1969
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001970 cur_arg = 1;
1971 while (*(args[cur_arg])) {
1972 if (!strcmp(args[cur_arg], "location")) {
1973 if (!*args[cur_arg + 1]) {
1974 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1975 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001978 }
1979
1980 type = REDIRECT_TYPE_LOCATION;
1981 cur_arg++;
1982 destination = args[cur_arg];
1983 }
1984 else if (!strcmp(args[cur_arg], "prefix")) {
1985 if (!*args[cur_arg + 1]) {
1986 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1987 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001990 }
1991
1992 type = REDIRECT_TYPE_PREFIX;
1993 cur_arg++;
1994 destination = args[cur_arg];
1995 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001996 else if (!strcmp(args[cur_arg], "set-cookie")) {
1997 if (!*args[cur_arg + 1]) {
1998 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1999 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002002 }
2003
2004 cur_arg++;
2005 cookie = args[cur_arg];
2006 cookie_set = 1;
2007 }
2008 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2009 if (!*args[cur_arg + 1]) {
2010 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2011 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002014 }
2015
2016 cur_arg++;
2017 cookie = args[cur_arg];
2018 cookie_set = 0;
2019 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002020 else if (!strcmp(args[cur_arg],"code")) {
2021 if (!*args[cur_arg + 1]) {
2022 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002026 }
2027 cur_arg++;
2028 code = atol(args[cur_arg]);
2029 if (code < 301 || code > 303) {
2030 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2031 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002034 }
2035 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002036 else if (!strcmp(args[cur_arg],"drop-query")) {
2037 flags |= REDIRECT_FLAG_DROP_QS;
2038 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002039 else if (!strcmp(args[cur_arg],"append-slash")) {
2040 flags |= REDIRECT_FLAG_APPEND_SLASH;
2041 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002042 else if (strcmp(args[cur_arg], "if") == 0 ||
2043 strcmp(args[cur_arg], "unless") == 0) {
2044 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2045 if (!cond) {
2046 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2047 file, linenum, args[0]);
2048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
2050 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002051 break;
2052 }
2053 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002054 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 +02002055 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002058 }
2059 cur_arg++;
2060 }
2061
2062 if (type == REDIRECT_TYPE_NONE) {
2063 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002067 }
2068
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002069 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2070 rule->cond = cond;
2071 rule->rdr_str = strdup(destination);
2072 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002073 if (cookie) {
2074 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2075 * a clear consists in appending "; Max-Age=0" at the end.
2076 */
2077 rule->cookie_len = strlen(cookie);
2078 if (cookie_set)
2079 rule->cookie_str = strdup(cookie);
2080 else {
2081 rule->cookie_str = malloc(rule->cookie_len + 12);
2082 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2083 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2084 rule->cookie_len += 11;
2085 }
2086 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002087 rule->type = type;
2088 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002089 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002090 LIST_INIT(&rule->list);
2091 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002092 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002093 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002094 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002095 struct switching_rule *rule;
2096
Willy Tarreaub099aca2008-10-12 17:26:37 +02002097 if (curproxy == &defproxy) {
2098 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002101 }
2102
Willy Tarreau55ea7572007-06-17 19:56:27 +02002103 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002105
2106 if (*(args[1]) == 0) {
2107 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002110 }
2111
Willy Tarreauef6494c2010-01-28 17:12:36 +01002112 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002113 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2114 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002117 }
2118
Willy Tarreauef6494c2010-01-28 17:12:36 +01002119 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002120 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002121 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_FATAL;
2123 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002124 }
2125
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002126 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002127
Willy Tarreau55ea7572007-06-17 19:56:27 +02002128 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2129 rule->cond = cond;
2130 rule->be.name = strdup(args[1]);
2131 LIST_INIT(&rule->list);
2132 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2133 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002134 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002135 struct force_persist_rule *rule;
2136
2137 if (curproxy == &defproxy) {
2138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
2141 }
2142
2143 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2144 err_code |= ERR_WARN;
2145
Willy Tarreauef6494c2010-01-28 17:12:36 +01002146 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002147 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2148 file, linenum, args[0]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152
Willy Tarreauef6494c2010-01-28 17:12:36 +01002153 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002154 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2155 file, linenum);
2156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
2158 }
2159
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002160 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002161
2162 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2163 rule->cond = cond;
2164 LIST_INIT(&rule->list);
2165 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2166 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002167 else if (!strcmp(args[0], "stick-table")) {
2168 int myidx = 1;
2169
2170 curproxy->table.type = (unsigned int)-1;
2171 while (*args[myidx]) {
2172 const char *err;
2173
2174 if (strcmp(args[myidx], "size") == 0) {
2175 myidx++;
2176 if (!*(args[myidx])) {
2177 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2178 file, linenum, args[myidx-1]);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2183 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2184 file, linenum, *err, args[myidx-1]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002188 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002189 }
2190 else if (strcmp(args[myidx], "expire") == 0) {
2191 myidx++;
2192 if (!*(args[myidx])) {
2193 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2194 file, linenum, args[myidx-1]);
2195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
2197 }
2198 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2199 if (err) {
2200 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2201 file, linenum, *err, args[myidx-1]);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002206 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002207 }
2208 else if (strcmp(args[myidx], "nopurge") == 0) {
2209 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002210 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002211 }
2212 else if (strcmp(args[myidx], "type") == 0) {
2213 myidx++;
2214 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2215 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2216 file, linenum, args[myidx]);
2217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
2219 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002220 /* myidx already points to next arg */
2221 }
2222 else {
2223 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2224 file, linenum, args[myidx]);
2225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002227 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002228 }
2229
2230 if (!curproxy->table.size) {
2231 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2232 file, linenum);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236
2237 if (curproxy->table.type == (unsigned int)-1) {
2238 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2239 file, linenum);
2240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
2242 }
2243 }
2244 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002245 struct sticking_rule *rule;
2246 struct pattern_expr *expr;
2247 int myidx = 0;
2248 const char *name = NULL;
2249 int flags;
2250
2251 if (curproxy == &defproxy) {
2252 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
2255 }
2256
2257 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2258 err_code |= ERR_WARN;
2259 goto out;
2260 }
2261
2262 myidx++;
2263 if ((strcmp(args[myidx], "store") == 0) ||
2264 (strcmp(args[myidx], "store-request") == 0)) {
2265 myidx++;
2266 flags = STK_IS_STORE;
2267 }
2268 else if (strcmp(args[myidx], "store-response") == 0) {
2269 myidx++;
2270 flags = STK_IS_STORE | STK_ON_RSP;
2271 }
2272 else if (strcmp(args[myidx], "match") == 0) {
2273 myidx++;
2274 flags = STK_IS_MATCH;
2275 }
2276 else if (strcmp(args[myidx], "on") == 0) {
2277 myidx++;
2278 flags = STK_IS_MATCH | STK_IS_STORE;
2279 }
2280 else {
2281 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
2285
2286 if (*(args[myidx]) == 0) {
2287 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
2292 expr = pattern_parse_expr(args, &myidx);
2293 if (!expr) {
2294 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298
2299 if (flags & STK_ON_RSP) {
2300 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2301 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2302 file, linenum, args[0], expr->fetch->kw);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306 } else {
2307 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2308 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2309 file, linenum, args[0], expr->fetch->kw);
2310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
2312 }
2313 }
2314
2315 if (strcmp(args[myidx], "table") == 0) {
2316 myidx++;
2317 name = args[myidx++];
2318 }
2319
Willy Tarreauef6494c2010-01-28 17:12:36 +01002320 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2321 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002322 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2323 file, linenum, args[0]);
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002327 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002328 else if (*(args[myidx])) {
2329 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2330 file, linenum, args[0], args[myidx]);
2331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
2333 }
2334
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002335 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2336
Emeric Brunb982a3d2010-01-04 15:45:53 +01002337 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2338 rule->cond = cond;
2339 rule->expr = expr;
2340 rule->flags = flags;
2341 rule->table.name = name ? strdup(name) : NULL;
2342 LIST_INIT(&rule->list);
2343 if (flags & STK_ON_RSP)
2344 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2345 else
2346 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002349 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002351
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2353 curproxy->uri_auth = NULL; /* we must detach from the default config */
2354
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002355 if (!*args[1]) {
2356 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 } else if (!strcmp(args[1], "uri")) {
2358 if (*(args[2]) == 0) {
2359 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2363 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002364 err_code |= ERR_ALERT | ERR_ABORT;
2365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
2367 } else if (!strcmp(args[1], "realm")) {
2368 if (*(args[2]) == 0) {
2369 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_ABORT;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002377 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002378 unsigned interval;
2379
2380 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2381 if (err) {
2382 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2383 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002386 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_ABORT;
2389 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 } else if (!strcmp(args[1], "auth")) {
2392 if (*(args[2]) == 0) {
2393 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2397 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_ABORT;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 } else if (!strcmp(args[1], "scope")) {
2402 if (*(args[2]) == 0) {
2403 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411 } else if (!strcmp(args[1], "enable")) {
2412 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2413 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_ABORT;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002417 } else if (!strcmp(args[1], "hide-version")) {
2418 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2419 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_ABORT;
2421 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002422 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002423 } else if (!strcmp(args[1], "show-legends")) {
2424 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2425 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2426 err_code |= ERR_ALERT | ERR_ABORT;
2427 goto out;
2428 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002429 } else if (!strcmp(args[1], "show-node")) {
2430
2431 if (*args[2]) {
2432 int i;
2433 char c;
2434
2435 for (i=0; args[2][i]; i++) {
2436 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002437 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002438 break;
2439 }
2440
2441 if (!i || args[2][i]) {
2442 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2443 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2444 file, linenum, args[0], args[1]);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448 }
2449
2450 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2451 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
2455 } else if (!strcmp(args[1], "show-desc")) {
2456 char *desc = NULL;
2457
2458 if (*args[2]) {
2459 int i, len=0;
2460 char *d;
2461
2462 for(i=2; *args[i]; i++)
2463 len += strlen(args[i])+1;
2464
2465 desc = d = (char *)calloc(1, len);
2466
2467 d += sprintf(d, "%s", args[2]);
2468 for(i=3; *args[i]; i++)
2469 d += sprintf(d, " %s", args[i]);
2470 }
2471
2472 if (!*args[2] && !global.desc)
2473 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2474 file, linenum, args[1]);
2475 else {
2476 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2477 free(desc);
2478 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2479 err_code |= ERR_ALERT | ERR_ABORT;
2480 goto out;
2481 }
2482 free(desc);
2483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002485stats_error_parsing:
2486 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2487 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 }
2491 }
2492 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002493 int optnum;
2494
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002495 if (*(args[1]) == '\0') {
2496 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002501
2502 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2503 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002504 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2505 err_code |= ERR_WARN;
2506 goto out;
2507 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002508
Willy Tarreau3842f002009-06-14 11:39:52 +02002509 curproxy->no_options &= ~cfg_opts[optnum].val;
2510 curproxy->options &= ~cfg_opts[optnum].val;
2511
2512 switch (kwm) {
2513 case KWM_STD:
2514 curproxy->options |= cfg_opts[optnum].val;
2515 break;
2516 case KWM_NO:
2517 curproxy->no_options |= cfg_opts[optnum].val;
2518 break;
2519 case KWM_DEF: /* already cleared */
2520 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002521 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002522
Willy Tarreau93893792009-07-23 13:19:11 +02002523 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002524 }
2525 }
2526
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002527 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2528 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002529 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2530 err_code |= ERR_WARN;
2531 goto out;
2532 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002533
Willy Tarreau3842f002009-06-14 11:39:52 +02002534 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2535 curproxy->options2 &= ~cfg_opts2[optnum].val;
2536
2537 switch (kwm) {
2538 case KWM_STD:
2539 curproxy->options2 |= cfg_opts2[optnum].val;
2540 break;
2541 case KWM_NO:
2542 curproxy->no_options2 |= cfg_opts2[optnum].val;
2543 break;
2544 case KWM_DEF: /* already cleared */
2545 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002546 }
Willy Tarreau93893792009-07-23 13:19:11 +02002547 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002548 }
2549 }
2550
Willy Tarreau3842f002009-06-14 11:39:52 +02002551 if (kwm != KWM_STD) {
2552 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002553 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002556 }
2557
Emeric Brun3a058f32009-06-30 18:26:00 +02002558 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002560 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002562 if (*(args[2]) != '\0') {
2563 if (!strcmp(args[2], "clf")) {
2564 curproxy->options2 |= PR_O2_CLFLOG;
2565 } else {
2566 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002569 }
2570 }
2571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 else if (!strcmp(args[1], "tcplog"))
2573 /* generate a detailed TCP log */
2574 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 else if (!strcmp(args[1], "tcpka")) {
2576 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002577 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002579
2580 if (curproxy->cap & PR_CAP_FE)
2581 curproxy->options |= PR_O_TCP_CLI_KA;
2582 if (curproxy->cap & PR_CAP_BE)
2583 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
2585 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002586 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_WARN;
2588
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002590 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002591 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002592 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002593 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002594 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 if (!*args[2]) { /* no argument */
2596 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2597 curproxy->check_len = strlen(DEF_CHECK_REQ);
2598 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002599 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 curproxy->check_req = (char *)malloc(reqlen);
2601 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002602 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002604 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 if (*args[4])
2606 reqlen += strlen(args[4]);
2607 else
2608 reqlen += strlen("HTTP/1.0");
2609
2610 curproxy->check_req = (char *)malloc(reqlen);
2611 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002612 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002614 }
2615 else if (!strcmp(args[1], "ssl-hello-chk")) {
2616 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002617 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002619
Willy Tarreaua534fea2008-08-03 12:19:50 +02002620 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002621 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002622 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002623 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002624 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 }
Willy Tarreau23677902007-05-08 23:50:35 +02002626 else if (!strcmp(args[1], "smtpchk")) {
2627 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002628 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002629 curproxy->options &= ~PR_O_HTTP_CHK;
2630 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002631 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002632 curproxy->options |= PR_O_SMTP_CHK;
2633
2634 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2635 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2636 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2637 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2638 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2639 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2640 curproxy->check_req = (char *)malloc(reqlen);
2641 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2642 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2643 } else {
2644 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2645 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2646 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2647 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2648 }
2649 }
2650 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002651 else if (!strcmp(args[1], "mysql-check")) {
2652 /* use MYSQL request to check servers' health */
2653 free(curproxy->check_req);
2654 curproxy->options &= ~PR_O_HTTP_CHK;
2655 curproxy->options &= ~PR_O_SSL3_CHK;
2656 curproxy->options &= ~PR_O_SMTP_CHK;
2657 curproxy->options2 |= PR_O2_MYSQL_CHK;
2658 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002659 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002660 int cur_arg;
2661
2662 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2663 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002664 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002665
2666 curproxy->options |= PR_O_FWDFOR;
2667
2668 free(curproxy->fwdfor_hdr_name);
2669 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2670 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2671
2672 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2673 cur_arg = 2;
2674 while (*(args[cur_arg])) {
2675 if (!strcmp(args[cur_arg], "except")) {
2676 /* suboption except - needs additional argument for it */
2677 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2678 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2679 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002682 }
2683 /* flush useless bits */
2684 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002685 cur_arg += 2;
2686 } else if (!strcmp(args[cur_arg], "header")) {
2687 /* suboption header - needs additional argument for it */
2688 if (*(args[cur_arg+1]) == 0) {
2689 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2690 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002693 }
2694 free(curproxy->fwdfor_hdr_name);
2695 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2696 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2697 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002698 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002699 /* unknown suboption - catchall */
2700 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2701 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002704 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002705 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002706 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002707 else if (!strcmp(args[1], "originalto")) {
2708 int cur_arg;
2709
2710 /* insert x-original-to field, but not for the IP address listed as an except.
2711 * set default options (ie: bitfield, header name, etc)
2712 */
2713
2714 curproxy->options |= PR_O_ORGTO;
2715
2716 free(curproxy->orgto_hdr_name);
2717 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2718 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2719
2720 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2721 cur_arg = 2;
2722 while (*(args[cur_arg])) {
2723 if (!strcmp(args[cur_arg], "except")) {
2724 /* suboption except - needs additional argument for it */
2725 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2726 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2727 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002730 }
2731 /* flush useless bits */
2732 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2733 cur_arg += 2;
2734 } else if (!strcmp(args[cur_arg], "header")) {
2735 /* suboption header - needs additional argument for it */
2736 if (*(args[cur_arg+1]) == 0) {
2737 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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;
Maik Broemme2850cb42009-04-17 18:53:21 +02002741 }
2742 free(curproxy->orgto_hdr_name);
2743 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2744 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2745 cur_arg += 2;
2746 } else {
2747 /* unknown suboption - catchall */
2748 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2749 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002752 }
2753 } /* end while loop */
2754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 else {
2756 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 }
Willy Tarreau93893792009-07-23 13:19:11 +02002760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002762 else if (!strcmp(args[0], "default_backend")) {
2763 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002765
2766 if (*(args[1]) == 0) {
2767 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002770 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002771 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002772 curproxy->defbe.name = strdup(args[1]);
2773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002777
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002778 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2779 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 /* enable reconnections to dispatch */
2782 curproxy->options |= PR_O_REDISP;
2783 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002784 else if (!strcmp(args[0], "http-check")) {
2785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002786 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002787
2788 if (strcmp(args[1], "disable-on-404") == 0) {
2789 /* enable a graceful server shutdown on an HTTP 404 response */
2790 curproxy->options |= PR_O_DISABLE404;
2791 }
Willy Tarreauef781042010-01-27 11:53:01 +01002792 else if (strcmp(args[1], "send-state") == 0) {
2793 /* enable emission of the apparent state of a server in HTTP checks */
2794 curproxy->options2 |= PR_O2_CHK_SNDST;
2795 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002796 else {
2797 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002800 }
2801 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002802 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002803 if (curproxy == &defproxy) {
2804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002807 }
2808
Willy Tarreaub80c2302007-11-30 20:51:32 +01002809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002811
2812 if (strcmp(args[1], "fail") == 0) {
2813 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002814 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002815 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2816 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002819 }
2820
Willy Tarreauef6494c2010-01-28 17:12:36 +01002821 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002822 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2823 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002826 }
2827 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2828 }
2829 else {
2830 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002833 }
2834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835#ifdef TPROXY
2836 else if (!strcmp(args[0], "transparent")) {
2837 /* enable transparent proxy connections */
2838 curproxy->options |= PR_O_TRANSP;
2839 }
2840#endif
2841 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002842 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002844
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 if (*(args[1]) == 0) {
2846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
2850 curproxy->maxconn = atol(args[1]);
2851 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002852 else if (!strcmp(args[0], "backlog")) { /* backlog */
2853 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002855
2856 if (*(args[1]) == 0) {
2857 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002860 }
2861 curproxy->backlog = atol(args[1]);
2862 }
Willy Tarreau86034312006-12-29 00:10:33 +01002863 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002865 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866
Willy Tarreau86034312006-12-29 00:10:33 +01002867 if (*(args[1]) == 0) {
2868 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002871 }
2872 curproxy->fullconn = atol(args[1]);
2873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2875 if (*(args[1]) == 0) {
2876 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002880 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2881 if (err) {
2882 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2883 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002886 }
2887 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
2889 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2890 if (curproxy == &defproxy) {
2891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002895 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002896 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 if (strchr(args[1], ':') == NULL) {
2899 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 }
2903 curproxy->dispatch_addr = *str2sa(args[1]);
2904 }
2905 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002909 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002910 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2911 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002916 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2917 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2918 err_code |= ERR_WARN;
2919
2920 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2921 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2922 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2923 }
2924 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2925 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2926 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2927 }
2928 else {
2929 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002934 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002936 char *rport, *raddr;
2937 short realport = 0;
2938 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002940 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947
2948 if (!*args[2]) {
2949 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2950 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 Tarreau2e74c3f2007-12-02 18:45:09 +01002954
2955 err = invalid_char(args[1]);
2956 if (err) {
2957 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2958 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002961 }
2962
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2964 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_ABORT;
2966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
2968
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002969 if (!defsrv) {
2970 /* the servers are linked backwards first */
2971 newsrv->next = curproxy->srv;
2972 curproxy->srv = newsrv;
2973 newsrv->proxy = curproxy;
2974 newsrv->conf.file = file;
2975 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002977 LIST_INIT(&newsrv->pendconns);
2978 do_check = 0;
2979 newsrv->state = SRV_RUNNING; /* early server setup */
2980 newsrv->last_change = now.tv_sec;
2981 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002983 /* several ways to check the port component :
2984 * - IP => port=+0, relative
2985 * - IP: => port=+0, relative
2986 * - IP:N => port=N, absolute
2987 * - IP:+N => port=+N, relative
2988 * - IP:-N => port=-N, relative
2989 */
2990 raddr = strdup(args[2]);
2991 rport = strchr(raddr, ':');
2992 if (rport) {
2993 *rport++ = 0;
2994 realport = atol(rport);
2995 if (!isdigit((unsigned char)*rport))
2996 newsrv->state |= SRV_MAPPORTS;
2997 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002999
3000 newsrv->addr = *str2sa(raddr);
3001 newsrv->addr.sin_port = htons(realport);
3002 free(raddr);
3003
3004 newsrv->check_port = curproxy->defsrv.check_port;
3005 newsrv->inter = curproxy->defsrv.inter;
3006 newsrv->fastinter = curproxy->defsrv.fastinter;
3007 newsrv->downinter = curproxy->defsrv.downinter;
3008 newsrv->rise = curproxy->defsrv.rise;
3009 newsrv->fall = curproxy->defsrv.fall;
3010 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3011 newsrv->minconn = curproxy->defsrv.minconn;
3012 newsrv->maxconn = curproxy->defsrv.maxconn;
3013 newsrv->slowstart = curproxy->defsrv.slowstart;
3014 newsrv->onerror = curproxy->defsrv.onerror;
3015 newsrv->consecutive_errors_limit
3016 = curproxy->defsrv.consecutive_errors_limit;
3017 newsrv->uweight = newsrv->iweight
3018 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003020 newsrv->curfd = -1; /* no health-check in progress */
3021 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003023 cur_arg = 3;
3024 } else {
3025 newsrv = &curproxy->defsrv;
3026 cur_arg = 1;
3027 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003028
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003030 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003031 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003032
3033 if (!*args[cur_arg + 1]) {
3034 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3035 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003038 }
3039
3040 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003041 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003042
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003043 if (newsrv->puid <= 0) {
3044 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003045 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003048 }
3049
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003050 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3051 if (node) {
3052 struct server *target = container_of(node, struct server, conf.id);
3053 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3054 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003059 cur_arg += 2;
3060 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003061 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 newsrv->cookie = strdup(args[cur_arg + 1]);
3063 newsrv->cklen = strlen(args[cur_arg + 1]);
3064 cur_arg += 2;
3065 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003066 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003067 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3068 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3069 cur_arg += 2;
3070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003072 if (!*args[cur_arg + 1]) {
3073 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3074 file, linenum, args[cur_arg]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003080 if (newsrv->rise <= 0) {
3081 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3082 file, linenum, args[cur_arg]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 newsrv->health = newsrv->rise;
3088 cur_arg += 2;
3089 }
3090 else if (!strcmp(args[cur_arg], "fall")) {
3091 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003092
3093 if (!*args[cur_arg + 1]) {
3094 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3095 file, linenum, args[cur_arg]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
3099
3100 if (newsrv->fall <= 0) {
3101 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3102 file, linenum, args[cur_arg]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 cur_arg += 2;
3108 }
3109 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003110 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3111 if (err) {
3112 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3113 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003116 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003117 if (val <= 0) {
3118 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3119 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003122 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003123 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 cur_arg += 2;
3125 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003126 else if (!strcmp(args[cur_arg], "fastinter")) {
3127 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3128 if (err) {
3129 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3130 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003133 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003134 if (val <= 0) {
3135 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3136 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003139 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003140 newsrv->fastinter = val;
3141 cur_arg += 2;
3142 }
3143 else if (!strcmp(args[cur_arg], "downinter")) {
3144 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3145 if (err) {
3146 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3147 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003150 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003151 if (val <= 0) {
3152 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3153 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003156 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003157 newsrv->downinter = val;
3158 cur_arg += 2;
3159 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003160 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003161 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003162 cur_arg += 2;
3163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 else if (!strcmp(args[cur_arg], "port")) {
3165 newsrv->check_port = atol(args[cur_arg + 1]);
3166 cur_arg += 2;
3167 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003168 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 newsrv->state |= SRV_BACKUP;
3170 cur_arg ++;
3171 }
3172 else if (!strcmp(args[cur_arg], "weight")) {
3173 int w;
3174 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003175 if (w < 0 || w > 256) {
3176 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003181 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 cur_arg += 2;
3183 }
3184 else if (!strcmp(args[cur_arg], "minconn")) {
3185 newsrv->minconn = atol(args[cur_arg + 1]);
3186 cur_arg += 2;
3187 }
3188 else if (!strcmp(args[cur_arg], "maxconn")) {
3189 newsrv->maxconn = atol(args[cur_arg + 1]);
3190 cur_arg += 2;
3191 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003192 else if (!strcmp(args[cur_arg], "maxqueue")) {
3193 newsrv->maxqueue = atol(args[cur_arg + 1]);
3194 cur_arg += 2;
3195 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003196 else if (!strcmp(args[cur_arg], "slowstart")) {
3197 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003198 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003199 if (err) {
3200 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3201 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003204 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003205 if (val <= 0) {
3206 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3207 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003210 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003211 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003212 cur_arg += 2;
3213 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003214 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003215
3216 if (!*args[cur_arg + 1]) {
3217 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3218 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003221 }
3222
3223 newsrv->trackit = strdup(args[cur_arg + 1]);
3224
3225 cur_arg += 2;
3226 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003227 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 global.maxsock++;
3229 do_check = 1;
3230 cur_arg += 1;
3231 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003232 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003233 if (!strcmp(args[cur_arg + 1], "none"))
3234 newsrv->observe = HANA_OBS_NONE;
3235 else if (!strcmp(args[cur_arg + 1], "layer4"))
3236 newsrv->observe = HANA_OBS_LAYER4;
3237 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3238 if (curproxy->mode != PR_MODE_HTTP) {
3239 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3240 file, linenum, args[cur_arg + 1]);
3241 err_code |= ERR_ALERT;
3242 }
3243 newsrv->observe = HANA_OBS_LAYER7;
3244 }
3245 else {
3246 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3247 "'l4events', 'http-responses' but get '%s'\n",
3248 file, linenum, args[cur_arg], args[cur_arg + 1]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 cur_arg += 2;
3254 }
3255 else if (!strcmp(args[cur_arg], "on-error")) {
3256 if (!strcmp(args[cur_arg + 1], "fastinter"))
3257 newsrv->onerror = HANA_ONERR_FASTINTER;
3258 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3259 newsrv->onerror = HANA_ONERR_FAILCHK;
3260 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3261 newsrv->onerror = HANA_ONERR_SUDDTH;
3262 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3263 newsrv->onerror = HANA_ONERR_MARKDWN;
3264 else {
3265 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3266 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3267 file, linenum, args[cur_arg], args[cur_arg + 1]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271
3272 cur_arg += 2;
3273 }
3274 else if (!strcmp(args[cur_arg], "error-limit")) {
3275 if (!*args[cur_arg + 1]) {
3276 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3277 file, linenum, args[cur_arg]);
3278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
3280 }
3281
3282 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3283
3284 if (newsrv->consecutive_errors_limit <= 0) {
3285 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3286 file, linenum, args[cur_arg]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003291 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003292 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003294#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003295 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003296 file, linenum, "source", "usesrc");
3297#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003298 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003300#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
3304 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003305 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3306
3307 if (port_low != port_high) {
3308 int i;
3309 if (port_low <= 0 || port_low > 65535 ||
3310 port_high <= 0 || port_high > 65535 ||
3311 port_low > port_high) {
3312 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3313 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003316 }
3317 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3318 for (i = 0; i < newsrv->sport_range->size; i++)
3319 newsrv->sport_range->ports[i] = port_low + i;
3320 }
3321
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003323 while (*(args[cur_arg])) {
3324 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003325#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3326#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003327 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3328 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3329 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003332 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003333#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003334 if (!*args[cur_arg + 1]) {
3335 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3336 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003339 }
3340 if (!strcmp(args[cur_arg + 1], "client")) {
3341 newsrv->state |= SRV_TPROXY_CLI;
3342 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3343 newsrv->state |= SRV_TPROXY_CIP;
3344 } else {
3345 newsrv->state |= SRV_TPROXY_ADDR;
3346 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3347 }
3348 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003349#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003350 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003351#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003352 cur_arg += 2;
3353 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003354#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003355 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003356 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003359#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3360 } /* "usesrc" */
3361
3362 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3363#ifdef SO_BINDTODEVICE
3364 if (!*args[cur_arg + 1]) {
3365 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003369 }
3370 if (newsrv->iface_name)
3371 free(newsrv->iface_name);
3372
3373 newsrv->iface_name = strdup(args[cur_arg + 1]);
3374 newsrv->iface_len = strlen(newsrv->iface_name);
3375 global.last_checks |= LSTCHK_NETADM;
3376#else
3377 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3378 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003381#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003382 cur_arg += 2;
3383 continue;
3384 }
3385 /* this keyword in not an option of "source" */
3386 break;
3387 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003389 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003390 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3391 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003396 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003397 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 +01003398 file, linenum, newsrv->id);
3399 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003400 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 +01003401 file, linenum);
3402
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406 }
3407
3408 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003409 if (newsrv->trackit) {
3410 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3411 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003414 }
3415
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003416 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3417 newsrv->check_port = newsrv->check_addr.sin_port;
3418
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3420 newsrv->check_port = realport; /* by default */
3421 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003422 /* not yet valid, because no port was set on
3423 * the server either. We'll check if we have
3424 * a known port on the first listener.
3425 */
3426 struct listener *l;
3427 l = curproxy->listen;
3428 if (l) {
3429 int port;
3430 port = (l->addr.ss_family == AF_INET6)
3431 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3432 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3433 newsrv->check_port = port;
3434 }
3435 }
3436 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3438 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003442
3443 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 newsrv->state |= SRV_CHECKED;
3445 }
3446
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003447 if (!defsrv) {
3448 if (newsrv->state & SRV_BACKUP)
3449 curproxy->srv_bck++;
3450 else
3451 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003452
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003453 newsrv->prev_state = newsrv->state;
3454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
3456 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003457 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 int facility;
3459
3460 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3461 curproxy->logfac1 = global.logfac1;
3462 curproxy->logsrv1 = global.logsrv1;
3463 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003464 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 curproxy->logfac2 = global.logfac2;
3466 curproxy->logsrv2 = global.logsrv2;
3467 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003468 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469 }
3470 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003471 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472
3473 facility = get_log_facility(args[2]);
3474 if (facility < 0) {
3475 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3476 exit(1);
3477 }
3478
3479 level = 7; /* max syslog level = debug */
3480 if (*(args[3])) {
3481 level = get_log_level(args[3]);
3482 if (level < 0) {
3483 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3484 exit(1);
3485 }
3486 }
3487
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003488 minlvl = 0; /* limit syslog level to this level (emerg) */
3489 if (*(args[4])) {
3490 minlvl = get_log_level(args[4]);
3491 if (level < 0) {
3492 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3493 exit(1);
3494 }
3495 }
3496
Robert Tsai81ae1952007-12-05 10:47:29 +01003497 if (args[1][0] == '/') {
3498 logsrv.u.addr.sa_family = AF_UNIX;
3499 logsrv.u.un = *str2sun(args[1]);
3500 } else {
3501 logsrv.u.addr.sa_family = AF_INET;
3502 logsrv.u.in = *str2sa(args[1]);
3503 if (!logsrv.u.in.sin_port) {
3504 logsrv.u.in.sin_port =
3505 htons(SYSLOG_PORT);
3506 }
3507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508
3509 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003510 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 curproxy->logfac1 = facility;
3512 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003513 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 }
3515 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003516 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 curproxy->logfac2 = facility;
3518 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003519 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
3521 else {
3522 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 }
3526 }
3527 else {
3528 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
3533 }
3534 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003535 int cur_arg;
3536
Willy Tarreau977b8e42006-12-29 14:19:17 +01003537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003539
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003541 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3542 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003546
3547 /* we must first clear any optional default setting */
3548 curproxy->options &= ~PR_O_TPXY_MASK;
3549 free(curproxy->iface_name);
3550 curproxy->iface_name = NULL;
3551 curproxy->iface_len = 0;
3552
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 curproxy->source_addr = *str2sa(args[1]);
3554 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003555
3556 cur_arg = 2;
3557 while (*(args[cur_arg])) {
3558 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003559#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3560#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003561 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3562 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3563 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003566 }
3567#endif
3568 if (!*args[cur_arg + 1]) {
3569 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3570 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003573 }
3574
3575 if (!strcmp(args[cur_arg + 1], "client")) {
3576 curproxy->options |= PR_O_TPXY_CLI;
3577 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3578 curproxy->options |= PR_O_TPXY_CIP;
3579 } else {
3580 curproxy->options |= PR_O_TPXY_ADDR;
3581 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3582 }
3583 global.last_checks |= LSTCHK_NETADM;
3584#if !defined(CONFIG_HAP_LINUX_TPROXY)
3585 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003586#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003587#else /* no TPROXY support */
3588 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003589 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003592#endif
3593 cur_arg += 2;
3594 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003595 }
3596
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003597 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3598#ifdef SO_BINDTODEVICE
3599 if (!*args[cur_arg + 1]) {
3600 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3601 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003604 }
3605 if (curproxy->iface_name)
3606 free(curproxy->iface_name);
3607
3608 curproxy->iface_name = strdup(args[cur_arg + 1]);
3609 curproxy->iface_len = strlen(curproxy->iface_name);
3610 global.last_checks |= LSTCHK_NETADM;
3611#else
3612 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3613 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003616#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003617 cur_arg += 2;
3618 continue;
3619 }
3620 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3621 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003626 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3627 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3628 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003633 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003639
3640 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3641 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003642 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003643 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
3646 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003647 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3648 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003649 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003650 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 }
3653 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003654 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3655 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003656 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003657 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 }
3660 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003661 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3662 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003663 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003664 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003666 }
3667 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003668 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3669 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003670 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003671 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003674 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003675 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3676 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003677 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003678 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003679 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003680 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003681 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003682 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3683 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003684 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003685 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003686 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003687 }
3688 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003689 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3690 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003691 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003692 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003693 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003696 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003702
3703 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3704 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003705 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003706 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003710 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3711 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003712 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003713 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
3716 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003717 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3718 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003719 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003720 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
3723 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003724 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3725 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003726 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003727 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 }
3730 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003731 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3732 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003733 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003734 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003737 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003738 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3739 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003740 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003741 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003742 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003745 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003746
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 if (*(args[1]) == 0) {
3756 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003759 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003760
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003761 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3762 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3763 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3764 file, linenum, args[0]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3769 }
3770 else if (*args[2]) {
3771 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3772 file, linenum, args[0], args[2]);
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
3776
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003777 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003778 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003779 wl->s = strdup(args[1]);
3780 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003781 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
3783 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003784 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3786 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003790
Willy Tarreauade5ec42010-01-28 19:33:49 +01003791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3792 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003793 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
3797 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3799 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
3804 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3806 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003807 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003812 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3814 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818
Willy Tarreauade5ec42010-01-28 19:33:49 +01003819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3820 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003821 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
3825 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3827 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003828 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831 }
3832 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3834 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003835 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
3839 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003840 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003841
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 if (curproxy == &defproxy) {
3843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003847 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 if (*(args[1]) == 0) {
3851 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 }
3855
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003856 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3857 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3858 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3859 file, linenum, args[0]);
3860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
3862 }
3863 err_code |= warnif_cond_requires_req(cond, file, linenum);
3864 }
3865 else if (*args[2]) {
3866 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3867 file, linenum, args[0], args[2]);
3868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
3870 }
3871
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003872 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003873 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003874 wl->s = strdup(args[1]);
3875 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877 else if (!strcmp(args[0], "errorloc") ||
3878 !strcmp(args[0], "errorloc302") ||
3879 !strcmp(args[0], "errorloc303")) { /* error location */
3880 int errnum, errlen;
3881 char *err;
3882
Willy Tarreau977b8e42006-12-29 14:19:17 +01003883 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003887 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
3891
3892 errnum = atol(args[1]);
3893 if (!strcmp(args[0], "errorloc303")) {
3894 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3895 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3896 } else {
3897 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3898 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3899 }
3900
Willy Tarreau0f772532006-12-23 20:51:41 +01003901 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3902 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003903 chunk_destroy(&curproxy->errmsg[rc]);
3904 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003905 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003908
3909 if (rc >= HTTP_ERR_SIZE) {
3910 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3911 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 free(err);
3913 }
3914 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003915 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3916 int errnum, errlen, fd;
3917 char *err;
3918 struct stat stat;
3919
3920 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003922
3923 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003924 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003927 }
3928
3929 fd = open(args[2], O_RDONLY);
3930 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3931 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3932 file, linenum, args[2], args[1]);
3933 if (fd >= 0)
3934 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003937 }
3938
Willy Tarreau27a674e2009-08-17 07:23:33 +02003939 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003940 errlen = stat.st_size;
3941 } else {
3942 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003943 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003945 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003946 }
3947
3948 err = malloc(errlen); /* malloc() must succeed during parsing */
3949 errnum = read(fd, err, errlen);
3950 if (errnum != errlen) {
3951 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3952 file, linenum, args[2], args[1]);
3953 close(fd);
3954 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003957 }
3958 close(fd);
3959
3960 errnum = atol(args[1]);
3961 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3962 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003963 chunk_destroy(&curproxy->errmsg[rc]);
3964 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003965 break;
3966 }
3967 }
3968
3969 if (rc >= HTTP_ERR_SIZE) {
3970 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3971 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003973 free(err);
3974 }
3975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003977 struct cfg_kw_list *kwl;
3978 int index;
3979
3980 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3981 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3982 if (kwl->kw[index].section != CFG_LISTEN)
3983 continue;
3984 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3985 /* prepare error message just in case */
3986 snprintf(trash, sizeof(trash),
3987 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003988 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3989 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003990 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003993 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003994 else if (rc > 0) {
3995 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_WARN;
3997 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003998 }
Willy Tarreau93893792009-07-23 13:19:11 +02003999 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004000 }
4001 }
4002 }
4003
Willy Tarreau6daf3432008-01-22 16:44:08 +01004004 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
Willy Tarreau93893792009-07-23 13:19:11 +02004008 out:
4009 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010}
4011
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004012int
4013cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4014{
4015
4016 int err_code = 0;
4017 const char *err;
4018
4019 if (!strcmp(args[0], "userlist")) { /* new userlist */
4020 struct userlist *newul;
4021
4022 if (!*args[1]) {
4023 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4024 file, linenum, args[0]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
4029 err = invalid_char(args[1]);
4030 if (err) {
4031 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4032 file, linenum, *err, args[0], args[1]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
4037 for (newul = userlist; newul; newul = newul->next)
4038 if (!strcmp(newul->name, args[1])) {
4039 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4040 file, linenum, args[1]);
4041 err_code |= ERR_WARN;
4042 goto out;
4043 }
4044
4045 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4046 if (!newul) {
4047 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4048 err_code |= ERR_ALERT | ERR_ABORT;
4049 goto out;
4050 }
4051
4052 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4053 newul->name = strdup(args[1]);
4054
4055 if (!newul->groupusers | !newul->name) {
4056 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4057 err_code |= ERR_ALERT | ERR_ABORT;
4058 goto out;
4059 }
4060
4061 newul->next = userlist;
4062 userlist = newul;
4063
4064 } else if (!strcmp(args[0], "group")) { /* new group */
4065 int cur_arg, i;
4066 const char *err;
4067
4068 if (!*args[1]) {
4069 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4070 file, linenum, args[0]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074
4075 err = invalid_char(args[1]);
4076 if (err) {
4077 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4078 file, linenum, *err, args[0], args[1]);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082
4083 for(i = 0; i < userlist->grpcnt; i++)
4084 if (!strcmp(userlist->groups[i], args[1])) {
4085 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4086 file, linenum, args[1], userlist->name);
4087 err_code |= ERR_ALERT;
4088 goto out;
4089 }
4090
4091 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4092 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4093 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097
4098 cur_arg = 2;
4099
4100 while (*args[cur_arg]) {
4101 if (!strcmp(args[cur_arg], "users")) {
4102 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4103 cur_arg += 2;
4104 continue;
4105 } else {
4106 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4107 file, linenum, args[0]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 }
4112
4113 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4114 } else if (!strcmp(args[0], "user")) { /* new user */
4115 struct auth_users *newuser;
4116 int cur_arg;
4117
4118 if (!*args[1]) {
4119 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4120 file, linenum, args[0]);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123 }
4124
4125 for (newuser = userlist->users; newuser; newuser = newuser->next)
4126 if (!strcmp(newuser->user, args[1])) {
4127 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4128 file, linenum, args[1], userlist->name);
4129 err_code |= ERR_ALERT;
4130 goto out;
4131 }
4132
4133 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4134 if (!newuser) {
4135 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4136 err_code |= ERR_ALERT | ERR_ABORT;
4137 goto out;
4138 }
4139
4140 newuser->user = strdup(args[1]);
4141
4142 newuser->next = userlist->users;
4143 userlist->users = newuser;
4144
4145 cur_arg = 2;
4146
4147 while (*args[cur_arg]) {
4148 if (!strcmp(args[cur_arg], "password")) {
4149#ifndef CONFIG_HAP_CRYPT
4150 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4151 file, linenum);
4152 err_code |= ERR_ALERT;
4153#endif
4154 newuser->pass = strdup(args[cur_arg + 1]);
4155 cur_arg += 2;
4156 continue;
4157 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4158 newuser->pass = strdup(args[cur_arg + 1]);
4159 newuser->flags |= AU_O_INSECURE;
4160 cur_arg += 2;
4161 continue;
4162 } else if (!strcmp(args[cur_arg], "groups")) {
4163 newuser->groups = strdup(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 continue;
4166 } else {
4167 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4168 file, linenum, args[0]);
4169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
4171 }
4172 }
4173 } else {
4174 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4175 err_code |= ERR_ALERT | ERR_FATAL;
4176 }
4177
4178out:
4179 return err_code;
4180}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181
4182/*
4183 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004184 * Returns the error code, 0 if OK, or any combination of :
4185 * - ERR_ABORT: must abort ASAP
4186 * - ERR_FATAL: we can continue parsing but not start the service
4187 * - ERR_WARN: a warning has been emitted
4188 * - ERR_ALERT: an alert has been emitted
4189 * Only the two first ones can stop processing, the two others are just
4190 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004192int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004194 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 FILE *f;
4196 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004198 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 if ((f=fopen(file,"r")) == NULL)
4201 return -1;
4202
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004203 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004204 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004205 char *end;
4206 char *args[MAX_LINE_ARGS + 1];
4207 char *line = thisline;
4208
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 linenum++;
4210
4211 end = line + strlen(line);
4212
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004213 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4214 /* Check if we reached the limit and the last char is not \n.
4215 * Watch out for the last line without the terminating '\n'!
4216 */
4217 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004218 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004220 }
4221
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004223 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 line++;
4225
4226 arg = 0;
4227 args[arg] = line;
4228
4229 while (*line && arg < MAX_LINE_ARGS) {
4230 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4231 * C equivalent value. Other combinations left unchanged (eg: \1).
4232 */
4233 if (*line == '\\') {
4234 int skip = 0;
4235 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4236 *line = line[1];
4237 skip = 1;
4238 }
4239 else if (line[1] == 'r') {
4240 *line = '\r';
4241 skip = 1;
4242 }
4243 else if (line[1] == 'n') {
4244 *line = '\n';
4245 skip = 1;
4246 }
4247 else if (line[1] == 't') {
4248 *line = '\t';
4249 skip = 1;
4250 }
4251 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004252 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 unsigned char hex1, hex2;
4254 hex1 = toupper(line[2]) - '0';
4255 hex2 = toupper(line[3]) - '0';
4256 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4257 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4258 *line = (hex1<<4) + hex2;
4259 skip = 3;
4260 }
4261 else {
4262 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004264 }
4265 }
4266 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004267 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004268 end -= skip;
4269 }
4270 line++;
4271 }
4272 else if (*line == '#' || *line == '\n' || *line == '\r') {
4273 /* end of string, end of loop */
4274 *line = 0;
4275 break;
4276 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004277 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004278 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004279 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004280 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 line++;
4282 args[++arg] = line;
4283 }
4284 else {
4285 line++;
4286 }
4287 }
4288
4289 /* empty line */
4290 if (!**args)
4291 continue;
4292
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004293 if (*line) {
4294 /* we had to stop due to too many args.
4295 * Let's terminate the string, print the offending part then cut the
4296 * last arg.
4297 */
4298 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4299 line++;
4300 *line = '\0';
4301
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004302 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004303 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 args[arg] = line;
4306 }
4307
Willy Tarreau540abe42007-05-02 20:50:16 +02004308 /* zero out remaining args and ensure that at least one entry
4309 * is zeroed out.
4310 */
4311 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 args[arg] = line;
4313 }
4314
Willy Tarreau3842f002009-06-14 11:39:52 +02004315 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004316 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004317 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004318 for (arg=0; *args[arg+1]; arg++)
4319 args[arg] = args[arg+1]; // shift args after inversion
4320 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004321 else if (!strcmp(args[0], "default")) {
4322 kwm = KWM_DEF;
4323 for (arg=0; *args[arg+1]; arg++)
4324 args[arg] = args[arg+1]; // shift args after inversion
4325 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004326
Willy Tarreau3842f002009-06-14 11:39:52 +02004327 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4328 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004330 }
4331
Willy Tarreau977b8e42006-12-29 14:19:17 +01004332 if (!strcmp(args[0], "listen") ||
4333 !strcmp(args[0], "frontend") ||
4334 !strcmp(args[0], "backend") ||
4335 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004336 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004338 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004339 cursection = strdup(args[0]);
4340 }
4341 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004343 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004344 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004345 } else if (!strcmp(args[0], "userlist")) {
4346 confsect = CFG_USERLIST;
4347 free(cursection);
4348 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004349 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 /* else it's a section keyword */
4351
4352 switch (confsect) {
4353 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355 break;
4356 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004357 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004359 case CFG_USERLIST:
4360 err_code |= cfg_parse_users(file, linenum, args, kwm);
4361 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004363 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004366
4367 if (err_code & ERR_ABORT)
4368 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004370 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004371 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004373 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004374}
4375
Willy Tarreaubb925012009-07-23 13:36:36 +02004376/*
4377 * Returns the error code, 0 if OK, or any combination of :
4378 * - ERR_ABORT: must abort ASAP
4379 * - ERR_FATAL: we can continue parsing but not start the service
4380 * - ERR_WARN: a warning has been emitted
4381 * - ERR_ALERT: an alert has been emitted
4382 * Only the two first ones can stop processing, the two others are just
4383 * indicators.
4384 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004385int check_config_validity()
4386{
4387 int cfgerr = 0;
4388 struct proxy *curproxy = NULL;
4389 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004390 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004391 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004392 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393
4394 /*
4395 * Now, check for the integrity of all that we have collected.
4396 */
4397
4398 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004399 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004401 /* first, we will invert the proxy list order */
4402 curproxy = NULL;
4403 while (proxy) {
4404 struct proxy *next;
4405
4406 next = proxy->next;
4407 proxy->next = curproxy;
4408 curproxy = proxy;
4409 if (!next)
4410 break;
4411 proxy = next;
4412 }
4413
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004415 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 }
4419
4420 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004421 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004422 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004423 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004424 unsigned int next_id;
4425
4426 if (!curproxy->uuid) {
4427 /* proxy ID not set, use automatic numbering with first
4428 * spare entry starting with next_pxid.
4429 */
4430 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4431 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4432 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4433 next_pxid++;
4434 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004435
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004437 /* ensure we don't keep listeners uselessly bound */
4438 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 curproxy = curproxy->next;
4440 continue;
4441 }
4442
Willy Tarreauff01a212009-03-15 13:46:16 +01004443 switch (curproxy->mode) {
4444 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004445 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004446 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004447 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4448 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004449 cfgerr++;
4450 }
4451
4452 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004453 Warning("config : servers will be ignored for %s '%s'.\n",
4454 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004455 break;
4456
4457 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004458 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004459 break;
4460
4461 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004462 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004463 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004464 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4465 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004466 cfgerr++;
4467 }
4468 break;
4469 }
4470
4471 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004472 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4473 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 cfgerr++;
4475 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004476
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004477 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004478 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004479 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004480 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4481 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004482 cfgerr++;
4483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004485 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004486 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4487 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004488 cfgerr++;
4489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004491 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004492 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4493 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004494 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004495 }
4496 }
4497 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4498 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4499 /* If no LB algo is set in a backend, and we're not in
4500 * transparent mode, dispatch mode nor proxy mode, we
4501 * want to use balance roundrobin by default.
4502 */
4503 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4504 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
4506 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004507
Willy Tarreau82936582007-11-30 15:20:09 +01004508 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4509 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004510 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4511 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004512 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004513 }
4514
Willy Tarreauef781042010-01-27 11:53:01 +01004515 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4516 curproxy->options &= ~PR_O2_CHK_SNDST;
4517 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4518 "send-state", proxy_type_str(curproxy), curproxy->id);
4519 err_code |= ERR_WARN;
4520 }
4521
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004522 /* if a default backend was specified, let's find it */
4523 if (curproxy->defbe.name) {
4524 struct proxy *target;
4525
Alex Williams96532db2009-11-01 21:27:13 -05004526 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004527 if (!target) {
4528 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4529 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004530 cfgerr++;
4531 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004532 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4533 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004534 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004535 } else {
4536 free(curproxy->defbe.name);
4537 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004538 /* we force the backend to be present on at least all of
4539 * the frontend's processes.
4540 */
4541 target->bind_proc = curproxy->bind_proc ?
4542 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 }
4544 }
4545
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004546 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004547 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4548 /* map jump target for ACT_SETBE in req_rep chain */
4549 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004550 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004551 struct proxy *target;
4552
Willy Tarreaua496b602006-12-17 23:15:24 +01004553 if (exp->action != ACT_SETBE)
4554 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004555
Alex Williams96532db2009-11-01 21:27:13 -05004556 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004557 if (!target) {
4558 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4559 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004560 cfgerr++;
4561 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004562 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4563 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004564 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004565 } else {
4566 free((void *)exp->replace);
4567 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004568 /* we force the backend to be present on at least all of
4569 * the frontend's processes.
4570 */
4571 target->bind_proc = curproxy->bind_proc ?
4572 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004573 }
4574 }
4575 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004576
4577 /* find the target proxy for 'use_backend' rules */
4578 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004579 struct proxy *target;
4580
Alex Williams96532db2009-11-01 21:27:13 -05004581 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004582
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004583 if (!target) {
4584 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4585 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004586 cfgerr++;
4587 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004588 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4589 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004590 cfgerr++;
4591 } else {
4592 free((void *)rule->be.name);
4593 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004594 /* we force the backend to be present on at least all of
4595 * the frontend's processes.
4596 */
4597 target->bind_proc = curproxy->bind_proc ?
4598 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004599 }
4600 }
4601
Emeric Brunb982a3d2010-01-04 15:45:53 +01004602 /* find the target table for 'stick' rules */
4603 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4604 struct proxy *target;
4605
Emeric Brun1d33b292010-01-04 15:47:17 +01004606 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4607 if (mrule->flags & STK_IS_STORE)
4608 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4609
Emeric Brunb982a3d2010-01-04 15:45:53 +01004610 if (mrule->table.name)
4611 target = findproxy(mrule->table.name, PR_CAP_BE);
4612 else
4613 target = curproxy;
4614
4615 if (!target) {
4616 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4617 curproxy->id, mrule->table.name);
4618 cfgerr++;
4619 }
4620 else if (target->table.size == 0) {
4621 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4622 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4623 cfgerr++;
4624 }
4625 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4626 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4627 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4628 cfgerr++;
4629 }
4630 else {
4631 free((void *)mrule->table.name);
4632 mrule->table.t = &(target->table);
4633 }
4634 }
4635
4636 /* find the target table for 'store response' rules */
4637 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4638 struct proxy *target;
4639
Emeric Brun1d33b292010-01-04 15:47:17 +01004640 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4641
Emeric Brunb982a3d2010-01-04 15:45:53 +01004642 if (mrule->table.name)
4643 target = findproxy(mrule->table.name, PR_CAP_BE);
4644 else
4645 target = curproxy;
4646
4647 if (!target) {
4648 Alert("Proxy '%s': unable to find store table '%s'.\n",
4649 curproxy->id, mrule->table.name);
4650 cfgerr++;
4651 }
4652 else if (target->table.size == 0) {
4653 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4654 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4655 cfgerr++;
4656 }
4657 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4658 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4659 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4660 cfgerr++;
4661 }
4662 else {
4663 free((void *)mrule->table.name);
4664 mrule->table.t = &(target->table);
4665 }
4666 }
4667
Willy Tarreau2738a142006-07-08 17:28:09 +02004668 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004669 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004670 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004671 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004672 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004673 " | While not properly invalid, you will certainly encounter various problems\n"
4674 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004675 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004676 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004677 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004678 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004679
Willy Tarreau1fa31262007-12-03 00:36:16 +01004680 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4681 * We must still support older configurations, so let's find out whether those
4682 * parameters have been set or must be copied from contimeouts.
4683 */
4684 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004685 if (!curproxy->timeout.tarpit ||
4686 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004687 /* tarpit timeout not set. We search in the following order:
4688 * default.tarpit, curr.connect, default.connect.
4689 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004690 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004691 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004692 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004693 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004694 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004695 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004696 }
4697 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004698 (!curproxy->timeout.queue ||
4699 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004700 /* queue timeout not set. We search in the following order:
4701 * default.queue, curr.connect, default.connect.
4702 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004703 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004704 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004705 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004706 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004707 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004708 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004709 }
4710 }
4711
Willy Tarreauf3c69202006-07-09 16:42:34 +02004712 if (curproxy->options & PR_O_SSL3_CHK) {
4713 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4714 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4715 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4716 }
4717
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004718 /* The small pools required for the capture lists */
4719 if (curproxy->nb_req_cap)
4720 curproxy->req_cap_pool = create_pool("ptrcap",
4721 curproxy->nb_req_cap * sizeof(char *),
4722 MEM_F_SHARED);
4723 if (curproxy->nb_rsp_cap)
4724 curproxy->rsp_cap_pool = create_pool("ptrcap",
4725 curproxy->nb_rsp_cap * sizeof(char *),
4726 MEM_F_SHARED);
4727
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004728 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4729 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4730 MEM_F_SHARED);
4731
Willy Tarreau86034312006-12-29 00:10:33 +01004732 /* for backwards compatibility with "listen" instances, if
4733 * fullconn is not set but maxconn is set, then maxconn
4734 * is used.
4735 */
4736 if (!curproxy->fullconn)
4737 curproxy->fullconn = curproxy->maxconn;
4738
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 /* first, we will invert the servers list order */
4740 newsrv = NULL;
4741 while (curproxy->srv) {
4742 struct server *next;
4743
4744 next = curproxy->srv->next;
4745 curproxy->srv->next = newsrv;
4746 newsrv = curproxy->srv;
4747 if (!next)
4748 break;
4749 curproxy->srv = next;
4750 }
4751
Willy Tarreau20697042007-11-15 23:26:18 +01004752 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004753 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004755 /* We have to initialize the server lookup mechanism depending
4756 * on what LB algorithm was choosen.
4757 */
4758
4759 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4760 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4761 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004762 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4763 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4764 init_server_map(curproxy);
4765 } else {
4766 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4767 fwrr_init_server_groups(curproxy);
4768 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004769 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004770
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004771 case BE_LB_KIND_LC:
4772 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004773 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004774 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004775
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004776 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004777 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4778 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4779 chash_init_server_tree(curproxy);
4780 } else {
4781 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4782 init_server_map(curproxy);
4783 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004784 break;
4785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786
4787 if (curproxy->options & PR_O_LOGASAP)
4788 curproxy->to_log &= ~LW_BYTES;
4789
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004790 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4791 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4792 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4793 proxy_type_str(curproxy), curproxy->id);
4794 err_code |= ERR_WARN;
4795 }
4796
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004798 * ensure that we're not cross-dressing a TCP server into HTTP.
4799 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004800 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004801 newsrv = curproxy->srv;
4802 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004803 if (!newsrv->puid) {
4804 /* server ID not set, use automatic numbering with first
4805 * spare entry starting with next_svid.
4806 */
4807 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4808 newsrv->conf.id.key = newsrv->puid = next_id;
4809 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4810 next_id++;
4811 }
4812
Willy Tarreau21d2af32008-02-14 20:25:24 +01004813 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004814 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4815 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004816 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004817 }
4818 newsrv = newsrv->next;
4819 }
4820
4821 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 * If this server supports a maxconn parameter, it needs a dedicated
4823 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004824 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 */
4826 newsrv = curproxy->srv;
4827 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004828 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 /* Only 'minconn' was specified, or it was higher than or equal
4830 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4831 * this will avoid further useless expensive computations.
4832 */
4833 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004834 } else if (newsrv->maxconn && !newsrv->minconn) {
4835 /* minconn was not specified, so we set it to maxconn */
4836 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004837 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004838 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4839 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004840 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
4842
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004843 if (newsrv->trackit) {
4844 struct proxy *px;
4845 struct server *srv;
4846 char *pname, *sname;
4847
4848 pname = newsrv->trackit;
4849 sname = strrchr(pname, '/');
4850
4851 if (sname)
4852 *sname++ = '\0';
4853 else {
4854 sname = pname;
4855 pname = NULL;
4856 }
4857
4858 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004859 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004860 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004861 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4862 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004863 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004864 cfgerr++;
4865 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004866 }
4867 } else
4868 px = curproxy;
4869
4870 srv = findserver(px, sname);
4871 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004872 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4873 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004874 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004875 cfgerr++;
4876 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004877 }
4878
4879 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004880 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004881 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004882 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004883 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004884 cfgerr++;
4885 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004886 }
4887
4888 if (curproxy != px &&
4889 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004890 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01004891 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004892 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004893 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004894 cfgerr++;
4895 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004896 }
4897
4898 newsrv->tracked = srv;
4899 newsrv->tracknext = srv->tracknext;
4900 srv->tracknext = newsrv;
4901
4902 free(newsrv->trackit);
4903 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004904 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 newsrv = newsrv->next;
4906 }
4907
Willy Tarreauc1a21672009-08-16 22:37:44 +02004908 if (curproxy->cap & PR_CAP_FE) {
4909 if (curproxy->tcp_req.inspect_delay ||
4910 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4911 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4912
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004913 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004914 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004915 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004916 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004917
4918 /* both TCP and HTTP must check switching rules */
4919 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4920 }
4921
4922 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004923 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004924 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004925 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004926 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004927
Emeric Brunb982a3d2010-01-04 15:45:53 +01004928 /* init table on backend capabilities proxy */
4929 stktable_init(&curproxy->table);
4930
Willy Tarreauc1a21672009-08-16 22:37:44 +02004931 /* If the backend does requires RDP cookie persistence, we have to
4932 * enable the corresponding analyser.
4933 */
4934 if (curproxy->options2 & PR_O2_RDPC_PRST)
4935 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4936 }
4937
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004938 listener = NULL;
4939 while (curproxy->listen) {
4940 struct listener *next;
4941
4942 next = curproxy->listen->next;
4943 curproxy->listen->next = listener;
4944 listener = curproxy->listen;
4945
4946 if (!next)
4947 break;
4948
4949 curproxy->listen = next;
4950 }
4951
Willy Tarreaue6b98942007-10-29 01:09:36 +01004952 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004953 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004954 listener = curproxy->listen;
4955 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004956 if (!listener->luid) {
4957 /* listener ID not set, use automatic numbering with first
4958 * spare entry starting with next_luid.
4959 */
4960 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4961 listener->conf.id.key = listener->luid = next_id;
4962 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4963 next_id++;
4964 }
4965
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004966 /* enable separate counters */
4967 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4968 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4969 if (!listener->name) {
4970 sprintf(trash, "sock-%d", listener->luid);
4971 listener->name = strdup(trash);
4972 }
4973 }
4974
Willy Tarreaue6b98942007-10-29 01:09:36 +01004975 if (curproxy->options & PR_O_TCP_NOLING)
4976 listener->options |= LI_O_NOLINGER;
4977 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004978 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004979 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004980 listener->accept = event_accept;
4981 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004982 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004983 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004984
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004985 /* smart accept mode is automatic in HTTP mode */
4986 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4987 (curproxy->mode == PR_MODE_HTTP &&
4988 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4989 listener->options |= LI_O_NOQUICKACK;
4990
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004991 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004992 listener = listener->next;
4993 }
4994
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 curproxy = curproxy->next;
4996 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004997
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004998 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
4999 struct auth_users *curuser;
5000 int g;
5001
5002 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5003 unsigned int group_mask = 0;
5004 char *group = NULL;
5005
5006 if (!curuser->groups)
5007 continue;
5008
5009 while ((group = strtok(group?NULL:curuser->groups, ","))) {
5010
5011 for (g = 0; g < curuserlist->grpcnt; g++)
5012 if (!strcmp(curuserlist->groups[g], group))
5013 break;
5014
5015 if (g == curuserlist->grpcnt) {
5016 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5017 curuserlist->name, group, curuser->user);
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
5021
5022 group_mask |= (1 << g);
5023 }
5024
5025 free(curuser->groups);
5026 curuser->group_mask = group_mask;
5027 }
5028
5029 for (g = 0; g < curuserlist->grpcnt; g++) {
5030 char *user = NULL;
5031
5032 if (!curuserlist->groupusers[g])
5033 continue;
5034
5035 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5036 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5037 if (!strcmp(curuser->user, user))
5038 break;
5039
5040 if (!curuser) {
5041 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5042 curuserlist->name, user, curuserlist->groups[g]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046
5047 curuser->group_mask |= (1 << g);
5048 }
5049
5050 free(curuserlist->groupusers[g]);
5051 }
5052
5053 free(curuserlist->groupusers);
5054
5055#ifdef DEBUG_AUTH
5056 for (g = 0; g < curuserlist->grpcnt; g++) {
5057 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5058
5059 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5060 if (curuser->group_mask & (1 << g))
5061 fprintf(stderr, " %s", curuser->user);
5062 }
5063
5064 fprintf(stderr, "\n");
5065 }
5066#endif
5067
5068 }
5069
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005070 /*
5071 * Recount currently required checks.
5072 */
5073
5074 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5075 int optnum;
5076
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005077 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5078 if (curproxy->options & cfg_opts[optnum].val)
5079 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005080
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005081 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5082 if (curproxy->options2 & cfg_opts2[optnum].val)
5083 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005084 }
5085
Willy Tarreaubb925012009-07-23 13:36:36 +02005086 if (cfgerr > 0)
5087 err_code |= ERR_ALERT | ERR_FATAL;
5088 out:
5089 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090}
5091
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005092/*
5093 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5094 * parsing sessions.
5095 */
5096void cfg_register_keywords(struct cfg_kw_list *kwl)
5097{
5098 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5099}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005101/*
5102 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5103 */
5104void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5105{
5106 LIST_DEL(&kwl->list);
5107 LIST_INIT(&kwl->list);
5108}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109
5110/*
5111 * Local variables:
5112 * c-indent-level: 8
5113 * c-basic-offset: 8
5114 * End:
5115 */