blob: 7f218db1ffa77bc09f7d7d1945b42fae0e038622 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
730 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
731 break;
732 }
733
734 if (!i || args[1][i]) {
735 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
736 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
737 file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741
742 if (global.node)
743 free(global.node);
744
745 global.node = strdup(args[1]);
746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 else if (!strcmp(args[0], "pidfile")) {
748 if (global.pidfile != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.pidfile = strdup(args[1]);
759 }
760 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200762 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763
764 if (*(args[1]) == 0 || *(args[2]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769
770 facility = get_log_facility(args[2]);
771 if (facility < 0) {
772 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776
777 level = 7; /* max syslog level = debug */
778 if (*(args[3])) {
779 level = get_log_level(args[3]);
780 if (level < 0) {
781 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 }
786
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200787 minlvl = 0; /* limit syslog level to this level (emerg) */
788 if (*(args[4])) {
789 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200794 }
795 }
796
Robert Tsai81ae1952007-12-05 10:47:29 +0100797 if (args[1][0] == '/') {
798 logsrv.u.addr.sa_family = AF_UNIX;
799 logsrv.u.un = *str2sun(args[1]);
800 } else {
801 logsrv.u.addr.sa_family = AF_INET;
802 logsrv.u.in = *str2sa(args[1]);
803 if (!logsrv.u.in.sin_port)
804 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806
807 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 global.logfac1 = facility;
810 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200811 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100814 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 global.logfac2 = facility;
816 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200817 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 else {
820 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200823 }
824 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
825 if (global.spread_checks != 0) {
826 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200827 err_code |= ERR_ALERT;
828 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200829 }
830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200834 }
835 global.spread_checks = atol(args[1]);
836 if (global.spread_checks < 0 || global.spread_checks > 50) {
837 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200842 struct cfg_kw_list *kwl;
843 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200844 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200845
846 list_for_each_entry(kwl, &cfg_keywords.list, list) {
847 for (index = 0; kwl->kw[index].kw != NULL; index++) {
848 if (kwl->kw[index].section != CFG_GLOBAL)
849 continue;
850 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
851 /* prepare error message just in case */
852 snprintf(trash, sizeof(trash),
853 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200854 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
855 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200858 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200859 else if (rc > 0) {
860 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200861 err_code |= ERR_WARN;
862 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200863 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200865 }
866 }
867 }
868
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200872
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 out:
874 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875}
876
Willy Tarreau97cb7802010-01-03 20:23:58 +0100877/* Perform the most basic initialization of a proxy :
878 * memset(), list_init(*), reset_timeouts(*).
879 */
880static void init_new_proxy(struct proxy *p)
881{
882 memset(p, 0, sizeof(struct proxy));
883 LIST_INIT(&p->pendconns);
884 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100885 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100886 LIST_INIT(&p->block_cond);
887 LIST_INIT(&p->redirect_rules);
888 LIST_INIT(&p->mon_fail_cond);
889 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100890 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100891 LIST_INIT(&p->sticking_rules);
892 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100893 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100894 LIST_INIT(&p->req_add);
895 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100896
897 /* Timeouts are defined as -1 */
898 proxy_reset_timeouts(p);
899}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200901void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 defproxy.mode = PR_MODE_TCP;
905 defproxy.state = PR_STNEW;
906 defproxy.maxconn = cfg_maxpconn;
907 defproxy.conn_retries = CONN_RETRIES;
908 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100909
910 defproxy.defsrv.inter = DEF_CHKINTR;
911 defproxy.defsrv.fastinter = 0;
912 defproxy.defsrv.downinter = 0;
913 defproxy.defsrv.rise = DEF_RISETIME;
914 defproxy.defsrv.fall = DEF_FALLTIME;
915 defproxy.defsrv.check_port = 0;
916 defproxy.defsrv.maxqueue = 0;
917 defproxy.defsrv.minconn = 0;
918 defproxy.defsrv.maxconn = 0;
919 defproxy.defsrv.slowstart = 0;
920 defproxy.defsrv.onerror = DEF_HANA_ONERR;
921 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
922 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923}
924
Willy Tarreauade5ec42010-01-28 19:33:49 +0100925
926static int create_cond_regex_rule(const char *file, int line,
927 struct proxy *px, int dir, int action, int flags,
928 const char *cmd, const char *reg, const char *repl,
929 const char **cond_start)
930{
931 regex_t *preg = NULL;
932 const char *err;
933 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100934 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100935
936 if (px == &defproxy) {
937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto err;
940 }
941
942 if (*reg == 0) {
943 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto err;
946 }
947
948 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
949 err_code |= ERR_WARN;
950
Willy Tarreau5321c422010-01-28 20:35:13 +0100951 if (cond_start &&
952 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
953 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
954 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
955 file, line, cmd);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto err;
958 }
959 }
960 else if (cond_start && **cond_start) {
961 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
962 file, line, cmd, *cond_start);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto err;
965 }
966
967 if (dir == ACL_DIR_REQ)
968 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100969 else
970 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100971
Willy Tarreauade5ec42010-01-28 19:33:49 +0100972 preg = calloc(1, sizeof(regex_t));
973 if (!preg) {
974 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
975 err_code = ERR_ALERT | ERR_FATAL;
976 goto err;
977 }
978
979 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
980 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
981 err_code = ERR_ALERT | ERR_FATAL;
982 goto err;
983 }
984
985 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100986 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +0100987 if (repl && err) {
988 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
989 file, line, cmd, *err);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto err;
992 }
993
994 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
995 err_code |= ERR_WARN;
996
997 return err_code;
998 err:
999 free(preg);
1000 return err_code;
1001}
1002
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001004 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001005 * Returns the error code, 0 if OK, or any combination of :
1006 * - ERR_ABORT: must abort ASAP
1007 * - ERR_FATAL: we can continue parsing but not start the service
1008 * - ERR_WARN: a warning has been emitted
1009 * - ERR_ALERT: an alert has been emitted
1010 * Only the two first ones can stop processing, the two others are just
1011 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001013int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014{
1015 static struct proxy *curproxy = NULL;
1016 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001017 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001018 int rc;
1019 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001020 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001021 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (!strcmp(args[0], "listen"))
1024 rc = PR_CAP_LISTEN;
1025 else if (!strcmp(args[0], "frontend"))
1026 rc = PR_CAP_FE | PR_CAP_RS;
1027 else if (!strcmp(args[0], "backend"))
1028 rc = PR_CAP_BE | PR_CAP_RS;
1029 else if (!strcmp(args[0], "ruleset"))
1030 rc = PR_CAP_RS;
1031 else
1032 rc = PR_CAP_NONE;
1033
1034 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 if (!*args[1]) {
1036 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1037 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001039 err_code |= ERR_ALERT | ERR_ABORT;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001042
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001043 err = invalid_char(args[1]);
1044 if (err) {
1045 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1046 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001048 }
1049
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001050 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1051 /*
1052 * If there are two proxies with the same name only following
1053 * combinations are allowed:
1054 *
1055 * listen backend frontend ruleset
1056 * listen - - - -
1057 * backend - - OK -
1058 * frontend - OK - -
1059 * ruleset - - - -
1060 */
1061
1062 if (!strcmp(curproxy->id, args[1]) &&
1063 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1064 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001065 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1066 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1067 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001068 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001069 }
1070 }
1071
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001074 err_code |= ERR_ALERT | ERR_ABORT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001077
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 curproxy->next = proxy;
1080 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001081 curproxy->conf.file = file;
1082 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001083 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086
1087 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001088 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001089 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001090 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_FATAL;
1092 goto out;
1093 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001094 new = curproxy->listen;
1095 while (new != last) {
1096 new->conf.file = file;
1097 new->conf.line = linenum;
1098 new = new->next;
1099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 global.maxsock++;
1101 }
1102
1103 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001104 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001108 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001109 curproxy->no_options = defproxy.no_options;
1110 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001111 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001112 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001113 curproxy->except_net = defproxy.except_net;
1114 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001115 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001116 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001118 if (defproxy.fwdfor_hdr_len) {
1119 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1120 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1121 }
1122
Willy Tarreaub86db342009-11-30 11:50:16 +01001123 if (defproxy.orgto_hdr_len) {
1124 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1125 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1126 }
1127
Willy Tarreau977b8e42006-12-29 14:19:17 +01001128 if (curproxy->cap & PR_CAP_FE) {
1129 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001130 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001131 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001132
1133 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001134 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1135 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001136
1137 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139
Willy Tarreau977b8e42006-12-29 14:19:17 +01001140 if (curproxy->cap & PR_CAP_BE) {
1141 curproxy->fullconn = defproxy.fullconn;
1142 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143
Willy Tarreau977b8e42006-12-29 14:19:17 +01001144 if (defproxy.check_req)
1145 curproxy->check_req = strdup(defproxy.check_req);
1146 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (defproxy.cookie_name)
1149 curproxy->cookie_name = strdup(defproxy.cookie_name);
1150 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001151 if (defproxy.cookie_domain)
1152 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001153
Emeric Brun647caf12009-06-30 17:57:00 +02001154 if (defproxy.rdp_cookie_name)
1155 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1156 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1157
Willy Tarreau01732802007-11-01 22:48:15 +01001158 if (defproxy.url_param_name)
1159 curproxy->url_param_name = strdup(defproxy.url_param_name);
1160 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001161
Benoitaffb4812009-03-25 13:02:10 +01001162 if (defproxy.hh_name)
1163 curproxy->hh_name = strdup(defproxy.hh_name);
1164 curproxy->hh_len = defproxy.hh_len;
1165 curproxy->hh_match_domain = defproxy.hh_match_domain;
1166
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001167 if (defproxy.iface_name)
1168 curproxy->iface_name = strdup(defproxy.iface_name);
1169 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001172 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001173 if (defproxy.capture_name)
1174 curproxy->capture_name = strdup(defproxy.capture_name);
1175 curproxy->capture_namelen = defproxy.capture_namelen;
1176 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178
Willy Tarreau977b8e42006-12-29 14:19:17 +01001179 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001180 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001181 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001182 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001183 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 curproxy->uri_auth = defproxy.uri_auth;
1185 curproxy->mon_net = defproxy.mon_net;
1186 curproxy->mon_mask = defproxy.mon_mask;
1187 if (defproxy.monitor_uri)
1188 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1189 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001190 if (defproxy.defbe.name)
1191 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 }
1193
1194 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001195 curproxy->timeout.connect = defproxy.timeout.connect;
1196 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001197 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001198 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001199 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001200 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001201 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001202 curproxy->source_addr = defproxy.source_addr;
1203 }
1204
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 curproxy->mode = defproxy.mode;
1206 curproxy->logfac1 = defproxy.logfac1;
1207 curproxy->logsrv1 = defproxy.logsrv1;
1208 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001209 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 curproxy->logfac2 = defproxy.logfac2;
1211 curproxy->logsrv2 = defproxy.logsrv2;
1212 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001213 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001215 curproxy->conf.used_listener_id = EB_ROOT;
1216 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001217
Willy Tarreau93893792009-07-23 13:19:11 +02001218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1221 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001222 /* FIXME-20070101: we should do this too at the end of the
1223 * config parsing to free all default values.
1224 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001225 free(defproxy.check_req);
1226 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001227 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001228 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001229 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001230 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001231 free(defproxy.capture_name);
1232 free(defproxy.monitor_uri);
1233 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001234 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001235 free(defproxy.fwdfor_hdr_name);
1236 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001237 free(defproxy.orgto_hdr_name);
1238 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001239
Willy Tarreaua534fea2008-08-03 12:19:50 +02001240 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001241 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001242
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 /* we cannot free uri_auth because it might already be used */
1244 init_default_instance();
1245 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001246 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 }
1249 else if (curproxy == NULL) {
1250 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254
Willy Tarreau977b8e42006-12-29 14:19:17 +01001255
1256 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001258 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001259 int cur_arg;
1260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (curproxy == &defproxy) {
1262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268
1269 if (strchr(args[1], ':') == NULL) {
1270 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001275
1276 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001277 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001281
Willy Tarreau90a570f2009-10-04 20:54:54 +02001282 new_listen = curproxy->listen;
1283 while (new_listen != last_listen) {
1284 new_listen->conf.file = file;
1285 new_listen->conf.line = linenum;
1286 new_listen = new_listen->next;
1287 }
1288
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001289 cur_arg = 2;
1290 while (*(args[cur_arg])) {
1291 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1292#ifdef SO_BINDTODEVICE
1293 struct listener *l;
1294
1295 if (!*args[cur_arg + 1]) {
1296 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001300 }
1301
1302 for (l = curproxy->listen; l != last_listen; l = l->next)
1303 l->interface = strdup(args[cur_arg + 1]);
1304
1305 global.last_checks |= LSTCHK_NETADM;
1306
1307 cur_arg += 2;
1308 continue;
1309#else
1310 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1311 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001314#endif
1315 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001316 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1317#ifdef TCP_MAXSEG
1318 struct listener *l;
1319 int mss;
1320
1321 if (!*args[cur_arg + 1]) {
1322 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001326 }
1327
1328 mss = str2uic(args[cur_arg + 1]);
1329 if (mss < 1 || mss > 65535) {
1330 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001334 }
1335
1336 for (l = curproxy->listen; l != last_listen; l = l->next)
1337 l->maxseg = mss;
1338
1339 cur_arg += 2;
1340 continue;
1341#else
1342 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1343 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001346#endif
1347 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001348
1349 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1350#ifdef TCP_DEFER_ACCEPT
1351 struct listener *l;
1352
1353 for (l = curproxy->listen; l != last_listen; l = l->next)
1354 l->options |= LI_O_DEF_ACCEPT;
1355
1356 cur_arg ++;
1357 continue;
1358#else
1359 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1360 file, linenum, args[0], args[cur_arg]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363#endif
1364 }
1365
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001366 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001367#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001368 struct listener *l;
1369
1370 for (l = curproxy->listen; l != last_listen; l = l->next)
1371 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001372
1373 cur_arg ++;
1374 continue;
1375#else
1376 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1377 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001382
1383 if (!strcmp(args[cur_arg], "name")) {
1384 struct listener *l;
1385
1386 for (l = curproxy->listen; l != last_listen; l = l->next)
1387 l->name = strdup(args[cur_arg + 1]);
1388
1389 cur_arg += 2;
1390 continue;
1391 }
1392
1393 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001394 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001395 struct listener *l;
1396
1397 if (curproxy->listen->next != last_listen) {
1398 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1399 file, linenum, args[cur_arg]);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
1402 }
1403
1404 if (!*args[cur_arg + 1]) {
1405 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1406 file, linenum, args[cur_arg]);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto out;
1409 }
1410
1411 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001412 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001413
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001414 if (curproxy->listen->luid <= 0) {
1415 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001416 file, linenum);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001421 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1422 if (node) {
1423 l = container_of(node, struct listener, conf.id);
1424 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1425 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1430
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001431 cur_arg += 2;
1432 continue;
1433 }
1434
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001435 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001436 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
1443 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1444 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1445 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 /* flush useless bits */
1454 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001457 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001459 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460
Willy Tarreau1c47f852006-07-09 08:22:27 +02001461 if (!*args[1]) {
1462 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001466 }
1467
Willy Tarreaua534fea2008-08-03 12:19:50 +02001468 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001469 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001470 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001471 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001472 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1473
Willy Tarreau93893792009-07-23 13:19:11 +02001474 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1477 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1478 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1479 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1480 else {
1481 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
1485 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001486 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001487 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001488
1489 if (curproxy == &defproxy) {
1490 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001494 }
1495
1496 if (!*args[1]) {
1497 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001501 }
1502
1503 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001504 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001506 if (curproxy->uuid <= 0) {
1507 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001511 }
1512
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001513 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1514 if (node) {
1515 struct proxy *target = container_of(node, struct proxy, conf.id);
1516 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1517 file, linenum, proxy_type_str(curproxy), curproxy->id,
1518 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001523 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001524 else if (!strcmp(args[0], "description")) {
1525 int i, len=0;
1526 char *d;
1527
Cyril Bonté99ed3272010-01-24 23:29:44 +01001528 if (curproxy == &defproxy) {
1529 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1530 file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001535 if (!*args[1]) {
1536 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1537 file, linenum, args[0]);
1538 return -1;
1539 }
1540
1541 for(i=1; *args[i]; i++)
1542 len += strlen(args[i])+1;
1543
1544 d = (char *)calloc(1, len);
1545 curproxy->desc = d;
1546
1547 d += sprintf(d, "%s", args[1]);
1548 for(i=2; *args[i]; i++)
1549 d += sprintf(d, " %s", args[i]);
1550
1551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1553 curproxy->state = PR_STSTOPPED;
1554 }
1555 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1556 curproxy->state = PR_STNEW;
1557 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001558 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1559 int cur_arg = 1;
1560 unsigned int set = 0;
1561
1562 while (*args[cur_arg]) {
1563 int u;
1564 if (strcmp(args[cur_arg], "all") == 0) {
1565 set = 0;
1566 break;
1567 }
1568 else if (strcmp(args[cur_arg], "odd") == 0) {
1569 set |= 0x55555555;
1570 }
1571 else if (strcmp(args[cur_arg], "even") == 0) {
1572 set |= 0xAAAAAAAA;
1573 }
1574 else {
1575 u = str2uic(args[cur_arg]);
1576 if (u < 1 || u > 32) {
1577 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1578 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001581 }
1582 if (u > global.nbproc) {
1583 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001586 }
1587 set |= 1 << (u - 1);
1588 }
1589 cur_arg++;
1590 }
1591 curproxy->bind_proc = set;
1592 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001593 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001594 if (curproxy == &defproxy) {
1595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001598 }
1599
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001600 err = invalid_char(args[1]);
1601 if (err) {
1602 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1603 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001605 }
1606
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1608 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1609 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001612 }
1613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1615 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 if (*(args[1]) == 0) {
1621 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001627 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001628 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 curproxy->cookie_name = strdup(args[1]);
1630 curproxy->cookie_len = strlen(curproxy->cookie_name);
1631
1632 cur_arg = 2;
1633 while (*(args[cur_arg])) {
1634 if (!strcmp(args[cur_arg], "rewrite")) {
1635 curproxy->options |= PR_O_COOK_RW;
1636 }
1637 else if (!strcmp(args[cur_arg], "indirect")) {
1638 curproxy->options |= PR_O_COOK_IND;
1639 }
1640 else if (!strcmp(args[cur_arg], "insert")) {
1641 curproxy->options |= PR_O_COOK_INS;
1642 }
1643 else if (!strcmp(args[cur_arg], "nocache")) {
1644 curproxy->options |= PR_O_COOK_NOC;
1645 }
1646 else if (!strcmp(args[cur_arg], "postonly")) {
1647 curproxy->options |= PR_O_COOK_POST;
1648 }
1649 else if (!strcmp(args[cur_arg], "prefix")) {
1650 curproxy->options |= PR_O_COOK_PFX;
1651 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001652 else if (!strcmp(args[cur_arg], "domain")) {
1653 if (!*args[cur_arg + 1]) {
1654 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1655 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001658 }
1659
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001660 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001661 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001662 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1663 " dots nor does not start with a dot."
1664 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001665 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001666 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001667 }
1668
1669 err = invalid_domainchar(args[cur_arg + 1]);
1670 if (err) {
1671 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1672 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 }
1676
Willy Tarreau68a897b2009-12-03 23:28:34 +01001677 if (!curproxy->cookie_domain) {
1678 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1679 } else {
1680 /* one domain was already specified, add another one by
1681 * building the string which will be returned along with
1682 * the cookie.
1683 */
1684 char *new_ptr;
1685 int new_len = strlen(curproxy->cookie_domain) +
1686 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1687 new_ptr = malloc(new_len);
1688 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1689 free(curproxy->cookie_domain);
1690 curproxy->cookie_domain = new_ptr;
1691 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001692 cur_arg++;
1693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001695 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
1700 cur_arg++;
1701 }
1702 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1703 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707
1708 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1709 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1710 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001714 else if (!strcmp(args[0], "persist")) { /* persist */
1715 if (*(args[1]) == 0) {
1716 Alert("parsing [%s:%d] : missing persist method.\n",
1717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001720 }
1721
1722 if (!strncmp(args[1], "rdp-cookie", 10)) {
1723 curproxy->options2 |= PR_O2_RDPC_PRST;
1724
Emeric Brunb982a3d2010-01-04 15:45:53 +01001725 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001726 const char *beg, *end;
1727
1728 beg = args[1] + 11;
1729 end = strchr(beg, ')');
1730
1731 if (!end || end == beg) {
1732 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1733 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001736 }
1737
1738 free(curproxy->rdp_cookie_name);
1739 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1740 curproxy->rdp_cookie_len = end-beg;
1741 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001742 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001743 free(curproxy->rdp_cookie_name);
1744 curproxy->rdp_cookie_name = strdup("msts");
1745 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1746 }
1747 else { /* syntax */
1748 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1749 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001752 }
1753 }
1754 else {
1755 Alert("parsing [%s:%d] : unknown persist method.\n",
1756 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001759 }
1760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001762 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001764 if (curproxy == &defproxy) {
1765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768 }
1769
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001774 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001780 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 curproxy->appsession_name = strdup(args[1]);
1782 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1783 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001784 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1785 if (err) {
1786 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1787 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001790 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001791 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001792
Willy Tarreau51041c72007-09-09 21:56:53 +02001793 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1794 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_ABORT;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001798
1799 cur_arg = 6;
1800 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001801 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1802 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001803 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001804 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001805 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001806 } else if (!strcmp(args[cur_arg], "prefix")) {
1807 curproxy->options2 |= PR_O2_AS_PFX;
1808 } else if (!strcmp(args[cur_arg], "mode")) {
1809 if (!*args[cur_arg + 1]) {
1810 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1811 file, linenum, args[0], args[cur_arg]);
1812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
1815
1816 cur_arg++;
1817 if (!strcmp(args[cur_arg], "query-string")) {
1818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1819 curproxy->options2 |= PR_O2_AS_M_QS;
1820 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1821 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1822 curproxy->options2 |= PR_O2_AS_M_PP;
1823 } else {
1824 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001829 cur_arg++;
1830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 } /* Url App Session */
1832 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001833 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 if (*(args[4]) == 0) {
1844 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001849 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 curproxy->capture_name = strdup(args[2]);
1851 curproxy->capture_namelen = strlen(curproxy->capture_name);
1852 curproxy->capture_len = atol(args[4]);
1853 if (curproxy->capture_len >= CAPTURE_LEN) {
1854 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1855 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 curproxy->capture_len = CAPTURE_LEN - 1;
1858 }
1859 curproxy->to_log |= LW_COOKIE;
1860 }
1861 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1862 struct cap_hdr *hdr;
1863
1864 if (curproxy == &defproxy) {
1865 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
1869
1870 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1871 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1872 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 }
1876
1877 hdr = calloc(sizeof(struct cap_hdr), 1);
1878 hdr->next = curproxy->req_cap;
1879 hdr->name = strdup(args[3]);
1880 hdr->namelen = strlen(args[3]);
1881 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001882 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 hdr->index = curproxy->nb_req_cap++;
1884 curproxy->req_cap = hdr;
1885 curproxy->to_log |= LW_REQHDR;
1886 }
1887 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1888 struct cap_hdr *hdr;
1889
1890 if (curproxy == &defproxy) {
1891 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
1895
1896 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1897 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1898 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
1902 hdr = calloc(sizeof(struct cap_hdr), 1);
1903 hdr->next = curproxy->rsp_cap;
1904 hdr->name = strdup(args[3]);
1905 hdr->namelen = strlen(args[3]);
1906 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001907 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 hdr->index = curproxy->nb_rsp_cap++;
1909 curproxy->rsp_cap = hdr;
1910 curproxy->to_log |= LW_RSPHDR;
1911 }
1912 else {
1913 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 }
1918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 if (*(args[1]) == 0) {
1924 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
1929 curproxy->conn_retries = atol(args[1]);
1930 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001931 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1932 struct req_acl_rule *req_acl;
1933
1934 if (curproxy == &defproxy) {
1935 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940
1941 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1942 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1943 file, linenum, args[0]);
1944 err_code |= ERR_WARN;
1945 }
1946
1947 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, &curproxy->acl, &curproxy->acl_requires);
1948
1949 if (!req_acl) {
1950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
1952 }
1953
1954 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1955 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001956 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001957 if (curproxy == &defproxy) {
1958 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001961 }
1962
Willy Tarreauef6494c2010-01-28 17:12:36 +01001963 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001964 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1965 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001968 }
1969
Willy Tarreauef6494c2010-01-28 17:12:36 +01001970 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001971 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1972 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_FATAL;
1974 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001975 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001976
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001977 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001978 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001979 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001980 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001981 struct redirect_rule *rule;
1982 int cur_arg;
1983 int type = REDIRECT_TYPE_NONE;
1984 int code = 302;
1985 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001986 char *cookie = NULL;
1987 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001988 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001989
Cyril Bonté99ed3272010-01-24 23:29:44 +01001990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
1994 }
1995
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 cur_arg = 1;
1997 while (*(args[cur_arg])) {
1998 if (!strcmp(args[cur_arg], "location")) {
1999 if (!*args[cur_arg + 1]) {
2000 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2001 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002004 }
2005
2006 type = REDIRECT_TYPE_LOCATION;
2007 cur_arg++;
2008 destination = args[cur_arg];
2009 }
2010 else if (!strcmp(args[cur_arg], "prefix")) {
2011 if (!*args[cur_arg + 1]) {
2012 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2013 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002014 err_code |= ERR_ALERT | ERR_FATAL;
2015 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002016 }
2017
2018 type = REDIRECT_TYPE_PREFIX;
2019 cur_arg++;
2020 destination = args[cur_arg];
2021 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002022 else if (!strcmp(args[cur_arg], "set-cookie")) {
2023 if (!*args[cur_arg + 1]) {
2024 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2025 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002028 }
2029
2030 cur_arg++;
2031 cookie = args[cur_arg];
2032 cookie_set = 1;
2033 }
2034 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2035 if (!*args[cur_arg + 1]) {
2036 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2037 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002040 }
2041
2042 cur_arg++;
2043 cookie = args[cur_arg];
2044 cookie_set = 0;
2045 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002046 else if (!strcmp(args[cur_arg],"code")) {
2047 if (!*args[cur_arg + 1]) {
2048 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002052 }
2053 cur_arg++;
2054 code = atol(args[cur_arg]);
2055 if (code < 301 || code > 303) {
2056 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2057 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002060 }
2061 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002062 else if (!strcmp(args[cur_arg],"drop-query")) {
2063 flags |= REDIRECT_FLAG_DROP_QS;
2064 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002065 else if (!strcmp(args[cur_arg],"append-slash")) {
2066 flags |= REDIRECT_FLAG_APPEND_SLASH;
2067 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002068 else if (strcmp(args[cur_arg], "if") == 0 ||
2069 strcmp(args[cur_arg], "unless") == 0) {
2070 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2071 if (!cond) {
2072 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2073 file, linenum, args[0]);
2074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
2076 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002077 break;
2078 }
2079 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002080 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 +02002081 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002084 }
2085 cur_arg++;
2086 }
2087
2088 if (type == REDIRECT_TYPE_NONE) {
2089 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2090 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002093 }
2094
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002095 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2096 rule->cond = cond;
2097 rule->rdr_str = strdup(destination);
2098 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002099 if (cookie) {
2100 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2101 * a clear consists in appending "; Max-Age=0" at the end.
2102 */
2103 rule->cookie_len = strlen(cookie);
2104 if (cookie_set)
2105 rule->cookie_str = strdup(cookie);
2106 else {
2107 rule->cookie_str = malloc(rule->cookie_len + 12);
2108 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2109 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2110 rule->cookie_len += 11;
2111 }
2112 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002113 rule->type = type;
2114 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002115 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002116 LIST_INIT(&rule->list);
2117 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002118 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002119 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002120 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002121 struct switching_rule *rule;
2122
Willy Tarreaub099aca2008-10-12 17:26:37 +02002123 if (curproxy == &defproxy) {
2124 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002127 }
2128
Willy Tarreau55ea7572007-06-17 19:56:27 +02002129 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002131
2132 if (*(args[1]) == 0) {
2133 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002136 }
2137
Willy Tarreauef6494c2010-01-28 17:12:36 +01002138 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002139 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2140 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002143 }
2144
Willy Tarreauef6494c2010-01-28 17:12:36 +01002145 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002146 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002147 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002150 }
2151
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002152 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002153
Willy Tarreau55ea7572007-06-17 19:56:27 +02002154 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2155 rule->cond = cond;
2156 rule->be.name = strdup(args[1]);
2157 LIST_INIT(&rule->list);
2158 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2159 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002160 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002161 struct force_persist_rule *rule;
2162
2163 if (curproxy == &defproxy) {
2164 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168
2169 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2170 err_code |= ERR_WARN;
2171
Willy Tarreauef6494c2010-01-28 17:12:36 +01002172 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002173 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2174 file, linenum, args[0]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
Willy Tarreauef6494c2010-01-28 17:12:36 +01002179 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002180 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2181 file, linenum);
2182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
2184 }
2185
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002186 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002187
2188 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2189 rule->cond = cond;
2190 LIST_INIT(&rule->list);
2191 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2192 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002193 else if (!strcmp(args[0], "stick-table")) {
2194 int myidx = 1;
2195
2196 curproxy->table.type = (unsigned int)-1;
2197 while (*args[myidx]) {
2198 const char *err;
2199
2200 if (strcmp(args[myidx], "size") == 0) {
2201 myidx++;
2202 if (!*(args[myidx])) {
2203 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2204 file, linenum, args[myidx-1]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2209 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2210 file, linenum, *err, args[myidx-1]);
2211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
2213 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002214 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002215 }
2216 else if (strcmp(args[myidx], "expire") == 0) {
2217 myidx++;
2218 if (!*(args[myidx])) {
2219 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2220 file, linenum, args[myidx-1]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2225 if (err) {
2226 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2227 file, linenum, *err, args[myidx-1]);
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002233 }
2234 else if (strcmp(args[myidx], "nopurge") == 0) {
2235 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002236 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002237 }
2238 else if (strcmp(args[myidx], "type") == 0) {
2239 myidx++;
2240 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2241 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2242 file, linenum, args[myidx]);
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002246 /* myidx already points to next arg */
2247 }
2248 else {
2249 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2250 file, linenum, args[myidx]);
2251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002253 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002254 }
2255
2256 if (!curproxy->table.size) {
2257 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2258 file, linenum);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263 if (curproxy->table.type == (unsigned int)-1) {
2264 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2265 file, linenum);
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
2268 }
2269 }
2270 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002271 struct sticking_rule *rule;
2272 struct pattern_expr *expr;
2273 int myidx = 0;
2274 const char *name = NULL;
2275 int flags;
2276
2277 if (curproxy == &defproxy) {
2278 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
2281 }
2282
2283 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2284 err_code |= ERR_WARN;
2285 goto out;
2286 }
2287
2288 myidx++;
2289 if ((strcmp(args[myidx], "store") == 0) ||
2290 (strcmp(args[myidx], "store-request") == 0)) {
2291 myidx++;
2292 flags = STK_IS_STORE;
2293 }
2294 else if (strcmp(args[myidx], "store-response") == 0) {
2295 myidx++;
2296 flags = STK_IS_STORE | STK_ON_RSP;
2297 }
2298 else if (strcmp(args[myidx], "match") == 0) {
2299 myidx++;
2300 flags = STK_IS_MATCH;
2301 }
2302 else if (strcmp(args[myidx], "on") == 0) {
2303 myidx++;
2304 flags = STK_IS_MATCH | STK_IS_STORE;
2305 }
2306 else {
2307 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311
2312 if (*(args[myidx]) == 0) {
2313 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
2317
2318 expr = pattern_parse_expr(args, &myidx);
2319 if (!expr) {
2320 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
2325 if (flags & STK_ON_RSP) {
2326 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2327 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2328 file, linenum, args[0], expr->fetch->kw);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332 } else {
2333 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2334 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2335 file, linenum, args[0], expr->fetch->kw);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339 }
2340
2341 if (strcmp(args[myidx], "table") == 0) {
2342 myidx++;
2343 name = args[myidx++];
2344 }
2345
Willy Tarreauef6494c2010-01-28 17:12:36 +01002346 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2347 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002348 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2349 file, linenum, args[0]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002353 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002354 else if (*(args[myidx])) {
2355 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2356 file, linenum, args[0], args[myidx]);
2357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
2359 }
2360
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002361 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2362
Emeric Brunb982a3d2010-01-04 15:45:53 +01002363 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2364 rule->cond = cond;
2365 rule->expr = expr;
2366 rule->flags = flags;
2367 rule->table.name = name ? strdup(name) : NULL;
2368 LIST_INIT(&rule->list);
2369 if (flags & STK_ON_RSP)
2370 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2371 else
2372 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002377
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2379 curproxy->uri_auth = NULL; /* we must detach from the default config */
2380
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002381 if (!*args[1]) {
2382 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 } else if (!strcmp(args[1], "uri")) {
2384 if (*(args[2]) == 0) {
2385 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_ABORT;
2391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }
2393 } else if (!strcmp(args[1], "realm")) {
2394 if (*(args[2]) == 0) {
2395 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002403 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002404 unsigned interval;
2405
2406 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2407 if (err) {
2408 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2409 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002412 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02002416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 } else if (!strcmp(args[1], "auth")) {
2418 if (*(args[2]) == 0) {
2419 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2423 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_ABORT;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 } else if (!strcmp(args[1], "scope")) {
2428 if (*(args[2]) == 0) {
2429 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_ABORT;
2435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 }
2437 } else if (!strcmp(args[1], "enable")) {
2438 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_ABORT;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002443 } else if (!strcmp(args[1], "hide-version")) {
2444 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2445 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_ABORT;
2447 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002448 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002449 } else if (!strcmp(args[1], "show-legends")) {
2450 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2451 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002455 } else if (!strcmp(args[1], "show-node")) {
2456
2457 if (*args[2]) {
2458 int i;
2459 char c;
2460
2461 for (i=0; args[2][i]; i++) {
2462 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002463 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002464 break;
2465 }
2466
2467 if (!i || args[2][i]) {
2468 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2469 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2470 file, linenum, args[0], args[1]);
2471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
2473 }
2474 }
2475
2476 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2477 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2478 err_code |= ERR_ALERT | ERR_ABORT;
2479 goto out;
2480 }
2481 } else if (!strcmp(args[1], "show-desc")) {
2482 char *desc = NULL;
2483
2484 if (*args[2]) {
2485 int i, len=0;
2486 char *d;
2487
2488 for(i=2; *args[i]; i++)
2489 len += strlen(args[i])+1;
2490
2491 desc = d = (char *)calloc(1, len);
2492
2493 d += sprintf(d, "%s", args[2]);
2494 for(i=3; *args[i]; i++)
2495 d += sprintf(d, " %s", args[i]);
2496 }
2497
2498 if (!*args[2] && !global.desc)
2499 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2500 file, linenum, args[1]);
2501 else {
2502 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2503 free(desc);
2504 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2505 err_code |= ERR_ALERT | ERR_ABORT;
2506 goto out;
2507 }
2508 free(desc);
2509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002511stats_error_parsing:
2512 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2513 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002516 }
2517 }
2518 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002519 int optnum;
2520
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002521 if (*(args[1]) == '\0') {
2522 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2523 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002527
2528 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2529 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002530 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2531 err_code |= ERR_WARN;
2532 goto out;
2533 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002534
Willy Tarreau3842f002009-06-14 11:39:52 +02002535 curproxy->no_options &= ~cfg_opts[optnum].val;
2536 curproxy->options &= ~cfg_opts[optnum].val;
2537
2538 switch (kwm) {
2539 case KWM_STD:
2540 curproxy->options |= cfg_opts[optnum].val;
2541 break;
2542 case KWM_NO:
2543 curproxy->no_options |= cfg_opts[optnum].val;
2544 break;
2545 case KWM_DEF: /* already cleared */
2546 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002547 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002548
Willy Tarreau93893792009-07-23 13:19:11 +02002549 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002550 }
2551 }
2552
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002553 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2554 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002555 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2556 err_code |= ERR_WARN;
2557 goto out;
2558 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002559
Willy Tarreau3842f002009-06-14 11:39:52 +02002560 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2561 curproxy->options2 &= ~cfg_opts2[optnum].val;
2562
2563 switch (kwm) {
2564 case KWM_STD:
2565 curproxy->options2 |= cfg_opts2[optnum].val;
2566 break;
2567 case KWM_NO:
2568 curproxy->no_options2 |= cfg_opts2[optnum].val;
2569 break;
2570 case KWM_DEF: /* already cleared */
2571 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002572 }
Willy Tarreau93893792009-07-23 13:19:11 +02002573 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002574 }
2575 }
2576
Willy Tarreau3842f002009-06-14 11:39:52 +02002577 if (kwm != KWM_STD) {
2578 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002579 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002582 }
2583
Emeric Brun3a058f32009-06-30 18:26:00 +02002584 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002586 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002588 if (*(args[2]) != '\0') {
2589 if (!strcmp(args[2], "clf")) {
2590 curproxy->options2 |= PR_O2_CLFLOG;
2591 } else {
2592 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002595 }
2596 }
2597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 else if (!strcmp(args[1], "tcplog"))
2599 /* generate a detailed TCP log */
2600 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 else if (!strcmp(args[1], "tcpka")) {
2602 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002603 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002605
2606 if (curproxy->cap & PR_CAP_FE)
2607 curproxy->options |= PR_O_TCP_CLI_KA;
2608 if (curproxy->cap & PR_CAP_BE)
2609 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 }
2611 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002612 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_WARN;
2614
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002616 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002617 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002618 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002619 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002620 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 if (!*args[2]) { /* no argument */
2622 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2623 curproxy->check_len = strlen(DEF_CHECK_REQ);
2624 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002625 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 curproxy->check_req = (char *)malloc(reqlen);
2627 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002628 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002630 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 if (*args[4])
2632 reqlen += strlen(args[4]);
2633 else
2634 reqlen += strlen("HTTP/1.0");
2635
2636 curproxy->check_req = (char *)malloc(reqlen);
2637 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002638 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002640 }
2641 else if (!strcmp(args[1], "ssl-hello-chk")) {
2642 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002643 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002645
Willy Tarreaua534fea2008-08-03 12:19:50 +02002646 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002647 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002648 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002649 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002650 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 }
Willy Tarreau23677902007-05-08 23:50:35 +02002652 else if (!strcmp(args[1], "smtpchk")) {
2653 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002654 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002655 curproxy->options &= ~PR_O_HTTP_CHK;
2656 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002657 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002658 curproxy->options |= PR_O_SMTP_CHK;
2659
2660 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2661 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2662 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2663 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2664 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2665 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2666 curproxy->check_req = (char *)malloc(reqlen);
2667 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2668 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2669 } else {
2670 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2671 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2672 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2673 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2674 }
2675 }
2676 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002677 else if (!strcmp(args[1], "mysql-check")) {
2678 /* use MYSQL request to check servers' health */
2679 free(curproxy->check_req);
2680 curproxy->options &= ~PR_O_HTTP_CHK;
2681 curproxy->options &= ~PR_O_SSL3_CHK;
2682 curproxy->options &= ~PR_O_SMTP_CHK;
2683 curproxy->options2 |= PR_O2_MYSQL_CHK;
2684 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002685 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002686 int cur_arg;
2687
2688 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2689 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002690 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002691
2692 curproxy->options |= PR_O_FWDFOR;
2693
2694 free(curproxy->fwdfor_hdr_name);
2695 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2696 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2697
2698 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2699 cur_arg = 2;
2700 while (*(args[cur_arg])) {
2701 if (!strcmp(args[cur_arg], "except")) {
2702 /* suboption except - needs additional argument for it */
2703 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2704 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2705 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002708 }
2709 /* flush useless bits */
2710 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002711 cur_arg += 2;
2712 } else if (!strcmp(args[cur_arg], "header")) {
2713 /* suboption header - needs additional argument for it */
2714 if (*(args[cur_arg+1]) == 0) {
2715 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2716 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002719 }
2720 free(curproxy->fwdfor_hdr_name);
2721 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2722 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2723 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002724 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002725 /* unknown suboption - catchall */
2726 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2727 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002730 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002731 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002732 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002733 else if (!strcmp(args[1], "originalto")) {
2734 int cur_arg;
2735
2736 /* insert x-original-to field, but not for the IP address listed as an except.
2737 * set default options (ie: bitfield, header name, etc)
2738 */
2739
2740 curproxy->options |= PR_O_ORGTO;
2741
2742 free(curproxy->orgto_hdr_name);
2743 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2744 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2745
2746 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2747 cur_arg = 2;
2748 while (*(args[cur_arg])) {
2749 if (!strcmp(args[cur_arg], "except")) {
2750 /* suboption except - needs additional argument for it */
2751 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2752 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2753 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002756 }
2757 /* flush useless bits */
2758 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2759 cur_arg += 2;
2760 } else if (!strcmp(args[cur_arg], "header")) {
2761 /* suboption header - needs additional argument for it */
2762 if (*(args[cur_arg+1]) == 0) {
2763 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2764 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002767 }
2768 free(curproxy->orgto_hdr_name);
2769 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2770 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2771 cur_arg += 2;
2772 } else {
2773 /* unknown suboption - catchall */
2774 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2775 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002778 }
2779 } /* end while loop */
2780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 else {
2782 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 }
Willy Tarreau93893792009-07-23 13:19:11 +02002786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002788 else if (!strcmp(args[0], "default_backend")) {
2789 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002791
2792 if (*(args[1]) == 0) {
2793 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002796 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002797 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002798 curproxy->defbe.name = strdup(args[1]);
2799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002800 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002801 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002803
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002804 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2805 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 /* enable reconnections to dispatch */
2808 curproxy->options |= PR_O_REDISP;
2809 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002810 else if (!strcmp(args[0], "http-check")) {
2811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002813
2814 if (strcmp(args[1], "disable-on-404") == 0) {
2815 /* enable a graceful server shutdown on an HTTP 404 response */
2816 curproxy->options |= PR_O_DISABLE404;
2817 }
Willy Tarreauef781042010-01-27 11:53:01 +01002818 else if (strcmp(args[1], "send-state") == 0) {
2819 /* enable emission of the apparent state of a server in HTTP checks */
2820 curproxy->options2 |= PR_O2_CHK_SNDST;
2821 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002822 else {
2823 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002826 }
2827 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002828 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002833 }
2834
Willy Tarreaub80c2302007-11-30 20:51:32 +01002835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002836 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002837
2838 if (strcmp(args[1], "fail") == 0) {
2839 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002840 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002841 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2842 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002845 }
2846
Willy Tarreauef6494c2010-01-28 17:12:36 +01002847 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002848 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2849 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002852 }
2853 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2854 }
2855 else {
2856 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002859 }
2860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861#ifdef TPROXY
2862 else if (!strcmp(args[0], "transparent")) {
2863 /* enable transparent proxy connections */
2864 curproxy->options |= PR_O_TRANSP;
2865 }
2866#endif
2867 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002868 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002869 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002870
Willy Tarreaubaaee002006-06-26 02:48:02 +02002871 if (*(args[1]) == 0) {
2872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
2876 curproxy->maxconn = atol(args[1]);
2877 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002878 else if (!strcmp(args[0], "backlog")) { /* backlog */
2879 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002881
2882 if (*(args[1]) == 0) {
2883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002886 }
2887 curproxy->backlog = atol(args[1]);
2888 }
Willy Tarreau86034312006-12-29 00:10:33 +01002889 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002890 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002892
Willy Tarreau86034312006-12-29 00:10:33 +01002893 if (*(args[1]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002897 }
2898 curproxy->fullconn = atol(args[1]);
2899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2901 if (*(args[1]) == 0) {
2902 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002906 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2907 if (err) {
2908 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2909 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002912 }
2913 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2916 if (curproxy == &defproxy) {
2917 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002921 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002922 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 if (strchr(args[1], ':') == NULL) {
2925 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
2929 curproxy->dispatch_addr = *str2sa(args[1]);
2930 }
2931 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002935 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002936 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2937 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002942 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2943 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2944 err_code |= ERR_WARN;
2945
2946 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2947 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2948 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2949 }
2950 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2951 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2952 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2953 }
2954 else {
2955 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002960 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002962 char *rport, *raddr;
2963 short realport = 0;
2964 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002966 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002971 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973
2974 if (!*args[2]) {
2975 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2976 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002980
2981 err = invalid_char(args[1]);
2982 if (err) {
2983 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2984 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002987 }
2988
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2990 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_ABORT;
2992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 }
2994
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002995 if (!defsrv) {
2996 /* the servers are linked backwards first */
2997 newsrv->next = curproxy->srv;
2998 curproxy->srv = newsrv;
2999 newsrv->proxy = curproxy;
3000 newsrv->conf.file = file;
3001 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003003 LIST_INIT(&newsrv->pendconns);
3004 do_check = 0;
3005 newsrv->state = SRV_RUNNING; /* early server setup */
3006 newsrv->last_change = now.tv_sec;
3007 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003009 /* several ways to check the port component :
3010 * - IP => port=+0, relative
3011 * - IP: => port=+0, relative
3012 * - IP:N => port=N, absolute
3013 * - IP:+N => port=+N, relative
3014 * - IP:-N => port=-N, relative
3015 */
3016 raddr = strdup(args[2]);
3017 rport = strchr(raddr, ':');
3018 if (rport) {
3019 *rport++ = 0;
3020 realport = atol(rport);
3021 if (!isdigit((unsigned char)*rport))
3022 newsrv->state |= SRV_MAPPORTS;
3023 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003025
3026 newsrv->addr = *str2sa(raddr);
3027 newsrv->addr.sin_port = htons(realport);
3028 free(raddr);
3029
3030 newsrv->check_port = curproxy->defsrv.check_port;
3031 newsrv->inter = curproxy->defsrv.inter;
3032 newsrv->fastinter = curproxy->defsrv.fastinter;
3033 newsrv->downinter = curproxy->defsrv.downinter;
3034 newsrv->rise = curproxy->defsrv.rise;
3035 newsrv->fall = curproxy->defsrv.fall;
3036 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3037 newsrv->minconn = curproxy->defsrv.minconn;
3038 newsrv->maxconn = curproxy->defsrv.maxconn;
3039 newsrv->slowstart = curproxy->defsrv.slowstart;
3040 newsrv->onerror = curproxy->defsrv.onerror;
3041 newsrv->consecutive_errors_limit
3042 = curproxy->defsrv.consecutive_errors_limit;
3043 newsrv->uweight = newsrv->iweight
3044 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003046 newsrv->curfd = -1; /* no health-check in progress */
3047 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003049 cur_arg = 3;
3050 } else {
3051 newsrv = &curproxy->defsrv;
3052 cur_arg = 1;
3053 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003056 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003057 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003058
3059 if (!*args[cur_arg + 1]) {
3060 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3061 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003064 }
3065
3066 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003067 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003068
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003069 if (newsrv->puid <= 0) {
3070 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003071 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003074 }
3075
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003076 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3077 if (node) {
3078 struct server *target = container_of(node, struct server, conf.id);
3079 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3080 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003085 cur_arg += 2;
3086 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003087 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 newsrv->cookie = strdup(args[cur_arg + 1]);
3089 newsrv->cklen = strlen(args[cur_arg + 1]);
3090 cur_arg += 2;
3091 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003092 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003093 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3094 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3095 cur_arg += 2;
3096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003098 if (!*args[cur_arg + 1]) {
3099 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3100 file, linenum, args[cur_arg]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003106 if (newsrv->rise <= 0) {
3107 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3108 file, linenum, args[cur_arg]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
3112
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 newsrv->health = newsrv->rise;
3114 cur_arg += 2;
3115 }
3116 else if (!strcmp(args[cur_arg], "fall")) {
3117 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003118
3119 if (!*args[cur_arg + 1]) {
3120 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3121 file, linenum, args[cur_arg]);
3122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
3124 }
3125
3126 if (newsrv->fall <= 0) {
3127 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3128 file, linenum, args[cur_arg]);
3129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
3131 }
3132
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 cur_arg += 2;
3134 }
3135 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003136 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3137 if (err) {
3138 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3139 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003142 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003143 if (val <= 0) {
3144 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3145 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003148 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003149 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 cur_arg += 2;
3151 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003152 else if (!strcmp(args[cur_arg], "fastinter")) {
3153 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3154 if (err) {
3155 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3156 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003159 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003160 if (val <= 0) {
3161 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3162 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003165 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003166 newsrv->fastinter = val;
3167 cur_arg += 2;
3168 }
3169 else if (!strcmp(args[cur_arg], "downinter")) {
3170 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3171 if (err) {
3172 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3173 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003176 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003177 if (val <= 0) {
3178 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3179 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003182 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003183 newsrv->downinter = val;
3184 cur_arg += 2;
3185 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003186 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003187 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003188 cur_arg += 2;
3189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 else if (!strcmp(args[cur_arg], "port")) {
3191 newsrv->check_port = atol(args[cur_arg + 1]);
3192 cur_arg += 2;
3193 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003194 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 newsrv->state |= SRV_BACKUP;
3196 cur_arg ++;
3197 }
3198 else if (!strcmp(args[cur_arg], "weight")) {
3199 int w;
3200 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003201 if (w < 0 || w > 256) {
3202 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003207 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 cur_arg += 2;
3209 }
3210 else if (!strcmp(args[cur_arg], "minconn")) {
3211 newsrv->minconn = atol(args[cur_arg + 1]);
3212 cur_arg += 2;
3213 }
3214 else if (!strcmp(args[cur_arg], "maxconn")) {
3215 newsrv->maxconn = atol(args[cur_arg + 1]);
3216 cur_arg += 2;
3217 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003218 else if (!strcmp(args[cur_arg], "maxqueue")) {
3219 newsrv->maxqueue = atol(args[cur_arg + 1]);
3220 cur_arg += 2;
3221 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003222 else if (!strcmp(args[cur_arg], "slowstart")) {
3223 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003224 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003225 if (err) {
3226 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3227 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003230 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003231 if (val <= 0) {
3232 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3233 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003236 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003237 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003238 cur_arg += 2;
3239 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003240 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003241
3242 if (!*args[cur_arg + 1]) {
3243 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3244 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003247 }
3248
3249 newsrv->trackit = strdup(args[cur_arg + 1]);
3250
3251 cur_arg += 2;
3252 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003253 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 global.maxsock++;
3255 do_check = 1;
3256 cur_arg += 1;
3257 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003258 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003259 if (!strcmp(args[cur_arg + 1], "none"))
3260 newsrv->observe = HANA_OBS_NONE;
3261 else if (!strcmp(args[cur_arg + 1], "layer4"))
3262 newsrv->observe = HANA_OBS_LAYER4;
3263 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3264 if (curproxy->mode != PR_MODE_HTTP) {
3265 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3266 file, linenum, args[cur_arg + 1]);
3267 err_code |= ERR_ALERT;
3268 }
3269 newsrv->observe = HANA_OBS_LAYER7;
3270 }
3271 else {
3272 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3273 "'l4events', 'http-responses' but get '%s'\n",
3274 file, linenum, args[cur_arg], args[cur_arg + 1]);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277 }
3278
3279 cur_arg += 2;
3280 }
3281 else if (!strcmp(args[cur_arg], "on-error")) {
3282 if (!strcmp(args[cur_arg + 1], "fastinter"))
3283 newsrv->onerror = HANA_ONERR_FASTINTER;
3284 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3285 newsrv->onerror = HANA_ONERR_FAILCHK;
3286 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3287 newsrv->onerror = HANA_ONERR_SUDDTH;
3288 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3289 newsrv->onerror = HANA_ONERR_MARKDWN;
3290 else {
3291 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3292 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3293 file, linenum, args[cur_arg], args[cur_arg + 1]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
3298 cur_arg += 2;
3299 }
3300 else if (!strcmp(args[cur_arg], "error-limit")) {
3301 if (!*args[cur_arg + 1]) {
3302 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3303 file, linenum, args[cur_arg]);
3304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
3306 }
3307
3308 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3309
3310 if (newsrv->consecutive_errors_limit <= 0) {
3311 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3312 file, linenum, args[cur_arg]);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003317 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003318 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003320#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003321 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003322 file, linenum, "source", "usesrc");
3323#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003324 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003326#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
3330 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003331 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3332
3333 if (port_low != port_high) {
3334 int i;
3335 if (port_low <= 0 || port_low > 65535 ||
3336 port_high <= 0 || port_high > 65535 ||
3337 port_low > port_high) {
3338 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3339 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003342 }
3343 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3344 for (i = 0; i < newsrv->sport_range->size; i++)
3345 newsrv->sport_range->ports[i] = port_low + i;
3346 }
3347
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003349 while (*(args[cur_arg])) {
3350 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003351#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3352#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003353 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3354 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3355 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003358 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003359#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003360 if (!*args[cur_arg + 1]) {
3361 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3362 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003365 }
3366 if (!strcmp(args[cur_arg + 1], "client")) {
3367 newsrv->state |= SRV_TPROXY_CLI;
3368 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3369 newsrv->state |= SRV_TPROXY_CIP;
3370 } else {
3371 newsrv->state |= SRV_TPROXY_ADDR;
3372 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3373 }
3374 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003375#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003376 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003377#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003378 cur_arg += 2;
3379 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003380#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003381 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003382 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003385#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3386 } /* "usesrc" */
3387
3388 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3389#ifdef SO_BINDTODEVICE
3390 if (!*args[cur_arg + 1]) {
3391 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003395 }
3396 if (newsrv->iface_name)
3397 free(newsrv->iface_name);
3398
3399 newsrv->iface_name = strdup(args[cur_arg + 1]);
3400 newsrv->iface_len = strlen(newsrv->iface_name);
3401 global.last_checks |= LSTCHK_NETADM;
3402#else
3403 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3404 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003407#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003408 cur_arg += 2;
3409 continue;
3410 }
3411 /* this keyword in not an option of "source" */
3412 break;
3413 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003415 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003416 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3417 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003422 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003423 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 +01003424 file, linenum, newsrv->id);
3425 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003426 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 +01003427 file, linenum);
3428
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
3432 }
3433
3434 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003435 if (newsrv->trackit) {
3436 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3437 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003440 }
3441
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003442 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3443 newsrv->check_port = newsrv->check_addr.sin_port;
3444
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3446 newsrv->check_port = realport; /* by default */
3447 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003448 /* not yet valid, because no port was set on
3449 * the server either. We'll check if we have
3450 * a known port on the first listener.
3451 */
3452 struct listener *l;
3453 l = curproxy->listen;
3454 if (l) {
3455 int port;
3456 port = (l->addr.ss_family == AF_INET6)
3457 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3458 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3459 newsrv->check_port = port;
3460 }
3461 }
3462 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3464 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003468
3469 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 newsrv->state |= SRV_CHECKED;
3471 }
3472
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003473 if (!defsrv) {
3474 if (newsrv->state & SRV_BACKUP)
3475 curproxy->srv_bck++;
3476 else
3477 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003478
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003479 newsrv->prev_state = newsrv->state;
3480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 }
3482 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003483 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 int facility;
3485
3486 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3487 curproxy->logfac1 = global.logfac1;
3488 curproxy->logsrv1 = global.logsrv1;
3489 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003490 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 curproxy->logfac2 = global.logfac2;
3492 curproxy->logsrv2 = global.logsrv2;
3493 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003494 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003497 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498
3499 facility = get_log_facility(args[2]);
3500 if (facility < 0) {
3501 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3502 exit(1);
3503 }
3504
3505 level = 7; /* max syslog level = debug */
3506 if (*(args[3])) {
3507 level = get_log_level(args[3]);
3508 if (level < 0) {
3509 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3510 exit(1);
3511 }
3512 }
3513
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003514 minlvl = 0; /* limit syslog level to this level (emerg) */
3515 if (*(args[4])) {
3516 minlvl = get_log_level(args[4]);
3517 if (level < 0) {
3518 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3519 exit(1);
3520 }
3521 }
3522
Robert Tsai81ae1952007-12-05 10:47:29 +01003523 if (args[1][0] == '/') {
3524 logsrv.u.addr.sa_family = AF_UNIX;
3525 logsrv.u.un = *str2sun(args[1]);
3526 } else {
3527 logsrv.u.addr.sa_family = AF_INET;
3528 logsrv.u.in = *str2sa(args[1]);
3529 if (!logsrv.u.in.sin_port) {
3530 logsrv.u.in.sin_port =
3531 htons(SYSLOG_PORT);
3532 }
3533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534
3535 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003536 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003537 curproxy->logfac1 = facility;
3538 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003539 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 }
3541 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003542 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 curproxy->logfac2 = facility;
3544 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003545 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
3547 else {
3548 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 }
3552 }
3553 else {
3554 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3555 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
3559 }
3560 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003561 int cur_arg;
3562
Willy Tarreau977b8e42006-12-29 14:19:17 +01003563 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003565
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003567 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3568 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003569 err_code |= ERR_ALERT | ERR_FATAL;
3570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003572
3573 /* we must first clear any optional default setting */
3574 curproxy->options &= ~PR_O_TPXY_MASK;
3575 free(curproxy->iface_name);
3576 curproxy->iface_name = NULL;
3577 curproxy->iface_len = 0;
3578
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 curproxy->source_addr = *str2sa(args[1]);
3580 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003581
3582 cur_arg = 2;
3583 while (*(args[cur_arg])) {
3584 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003585#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3586#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003587 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3588 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3589 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 }
3593#endif
3594 if (!*args[cur_arg + 1]) {
3595 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3596 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003599 }
3600
3601 if (!strcmp(args[cur_arg + 1], "client")) {
3602 curproxy->options |= PR_O_TPXY_CLI;
3603 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3604 curproxy->options |= PR_O_TPXY_CIP;
3605 } else {
3606 curproxy->options |= PR_O_TPXY_ADDR;
3607 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3608 }
3609 global.last_checks |= LSTCHK_NETADM;
3610#if !defined(CONFIG_HAP_LINUX_TPROXY)
3611 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003612#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003613#else /* no TPROXY support */
3614 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003615 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003618#endif
3619 cur_arg += 2;
3620 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003621 }
3622
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003623 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3624#ifdef SO_BINDTODEVICE
3625 if (!*args[cur_arg + 1]) {
3626 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003630 }
3631 if (curproxy->iface_name)
3632 free(curproxy->iface_name);
3633
3634 curproxy->iface_name = strdup(args[cur_arg + 1]);
3635 curproxy->iface_len = strlen(curproxy->iface_name);
3636 global.last_checks |= LSTCHK_NETADM;
3637#else
3638 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3639 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003642#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003643 cur_arg += 2;
3644 continue;
3645 }
3646 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3647 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003652 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3653 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3654 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003659 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3661 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003665
3666 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3667 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003668 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003669 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 }
3672 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003673 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3674 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003675 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003676 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003680 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3681 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003682 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003683 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 }
3686 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003687 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3688 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003689 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003690 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
3693 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003694 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3695 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003696 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003697 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003700 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003701 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3702 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003703 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003704 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003705 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003706 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003707 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003708 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3709 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003710 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003711 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003712 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003713 }
3714 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003715 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3716 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003717 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003718 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003719 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003722 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3724 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003728
3729 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3730 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003731 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003732 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 }
3735 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003736 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3737 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003738 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003739 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 }
3742 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003743 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3744 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003745 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003746 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 }
3749 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003750 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3751 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003752 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003753 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 }
3756 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3758 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003759 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003763 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3765 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003766 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003768 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003771 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003772
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 if (curproxy == &defproxy) {
3774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 if (*(args[1]) == 0) {
3782 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003786
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003787 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3788 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3789 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3790 file, linenum, args[0]);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3795 }
3796 else if (*args[2]) {
3797 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3798 file, linenum, args[0], args[2]);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003803 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003804 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003805 wl->s = strdup(args[1]);
3806 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003807 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
3809 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003810 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3812 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816
Willy Tarreauade5ec42010-01-28 19:33:49 +01003817 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3818 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003819 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003820 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003824 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3825 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003826 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003827 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 }
3830 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003831 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3832 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003833 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003834 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
3837 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003838 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3840 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 }
3844
Willy Tarreauade5ec42010-01-28 19:33:49 +01003845 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3846 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003847 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003848 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003852 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3853 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003854 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003855 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003859 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3860 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003861 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003862 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 }
3865 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003866 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003867
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 if (curproxy == &defproxy) {
3869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003873 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 if (*(args[1]) == 0) {
3877 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
3881
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003882 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3883 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3884 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3885 file, linenum, args[0]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 err_code |= warnif_cond_requires_req(cond, file, linenum);
3890 }
3891 else if (*args[2]) {
3892 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3893 file, linenum, args[0], args[2]);
3894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
3896 }
3897
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003898 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003899 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003900 wl->s = strdup(args[1]);
3901 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 }
3903 else if (!strcmp(args[0], "errorloc") ||
3904 !strcmp(args[0], "errorloc302") ||
3905 !strcmp(args[0], "errorloc303")) { /* error location */
3906 int errnum, errlen;
3907 char *err;
3908
Willy Tarreau977b8e42006-12-29 14:19:17 +01003909 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003913 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003916 }
3917
3918 errnum = atol(args[1]);
3919 if (!strcmp(args[0], "errorloc303")) {
3920 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3921 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3922 } else {
3923 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3924 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3925 }
3926
Willy Tarreau0f772532006-12-23 20:51:41 +01003927 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3928 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003929 chunk_destroy(&curproxy->errmsg[rc]);
3930 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003931 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003934
3935 if (rc >= HTTP_ERR_SIZE) {
3936 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3937 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 free(err);
3939 }
3940 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003941 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3942 int errnum, errlen, fd;
3943 char *err;
3944 struct stat stat;
3945
3946 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003948
3949 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003950 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003953 }
3954
3955 fd = open(args[2], O_RDONLY);
3956 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3957 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3958 file, linenum, args[2], args[1]);
3959 if (fd >= 0)
3960 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003963 }
3964
Willy Tarreau27a674e2009-08-17 07:23:33 +02003965 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003966 errlen = stat.st_size;
3967 } else {
3968 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003969 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003971 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003972 }
3973
3974 err = malloc(errlen); /* malloc() must succeed during parsing */
3975 errnum = read(fd, err, errlen);
3976 if (errnum != errlen) {
3977 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3978 file, linenum, args[2], args[1]);
3979 close(fd);
3980 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003983 }
3984 close(fd);
3985
3986 errnum = atol(args[1]);
3987 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3988 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003989 chunk_destroy(&curproxy->errmsg[rc]);
3990 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003991 break;
3992 }
3993 }
3994
3995 if (rc >= HTTP_ERR_SIZE) {
3996 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3997 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003999 free(err);
4000 }
4001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004003 struct cfg_kw_list *kwl;
4004 int index;
4005
4006 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4007 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4008 if (kwl->kw[index].section != CFG_LISTEN)
4009 continue;
4010 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4011 /* prepare error message just in case */
4012 snprintf(trash, sizeof(trash),
4013 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004014 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4015 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004016 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004019 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004020 else if (rc > 0) {
4021 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_WARN;
4023 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004024 }
Willy Tarreau93893792009-07-23 13:19:11 +02004025 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004026 }
4027 }
4028 }
4029
Willy Tarreau6daf3432008-01-22 16:44:08 +01004030 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 }
Willy Tarreau93893792009-07-23 13:19:11 +02004034 out:
4035 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036}
4037
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004038int
4039cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4040{
4041
4042 int err_code = 0;
4043 const char *err;
4044
4045 if (!strcmp(args[0], "userlist")) { /* new userlist */
4046 struct userlist *newul;
4047
4048 if (!*args[1]) {
4049 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4050 file, linenum, args[0]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
4055 err = invalid_char(args[1]);
4056 if (err) {
4057 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4058 file, linenum, *err, args[0], args[1]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
4063 for (newul = userlist; newul; newul = newul->next)
4064 if (!strcmp(newul->name, args[1])) {
4065 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4066 file, linenum, args[1]);
4067 err_code |= ERR_WARN;
4068 goto out;
4069 }
4070
4071 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4072 if (!newul) {
4073 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4074 err_code |= ERR_ALERT | ERR_ABORT;
4075 goto out;
4076 }
4077
4078 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4079 newul->name = strdup(args[1]);
4080
4081 if (!newul->groupusers | !newul->name) {
4082 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4083 err_code |= ERR_ALERT | ERR_ABORT;
4084 goto out;
4085 }
4086
4087 newul->next = userlist;
4088 userlist = newul;
4089
4090 } else if (!strcmp(args[0], "group")) { /* new group */
4091 int cur_arg, i;
4092 const char *err;
4093
4094 if (!*args[1]) {
4095 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4096 file, linenum, args[0]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100
4101 err = invalid_char(args[1]);
4102 if (err) {
4103 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4104 file, linenum, *err, args[0], args[1]);
4105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108
4109 for(i = 0; i < userlist->grpcnt; i++)
4110 if (!strcmp(userlist->groups[i], args[1])) {
4111 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4112 file, linenum, args[1], userlist->name);
4113 err_code |= ERR_ALERT;
4114 goto out;
4115 }
4116
4117 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4118 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4119 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123
4124 cur_arg = 2;
4125
4126 while (*args[cur_arg]) {
4127 if (!strcmp(args[cur_arg], "users")) {
4128 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4129 cur_arg += 2;
4130 continue;
4131 } else {
4132 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4133 file, linenum, args[0]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 }
4138
4139 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4140 } else if (!strcmp(args[0], "user")) { /* new user */
4141 struct auth_users *newuser;
4142 int cur_arg;
4143
4144 if (!*args[1]) {
4145 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4146 file, linenum, args[0]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150
4151 for (newuser = userlist->users; newuser; newuser = newuser->next)
4152 if (!strcmp(newuser->user, args[1])) {
4153 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4154 file, linenum, args[1], userlist->name);
4155 err_code |= ERR_ALERT;
4156 goto out;
4157 }
4158
4159 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4160 if (!newuser) {
4161 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4162 err_code |= ERR_ALERT | ERR_ABORT;
4163 goto out;
4164 }
4165
4166 newuser->user = strdup(args[1]);
4167
4168 newuser->next = userlist->users;
4169 userlist->users = newuser;
4170
4171 cur_arg = 2;
4172
4173 while (*args[cur_arg]) {
4174 if (!strcmp(args[cur_arg], "password")) {
4175#ifndef CONFIG_HAP_CRYPT
4176 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4177 file, linenum);
4178 err_code |= ERR_ALERT;
4179#endif
4180 newuser->pass = strdup(args[cur_arg + 1]);
4181 cur_arg += 2;
4182 continue;
4183 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4184 newuser->pass = strdup(args[cur_arg + 1]);
4185 newuser->flags |= AU_O_INSECURE;
4186 cur_arg += 2;
4187 continue;
4188 } else if (!strcmp(args[cur_arg], "groups")) {
4189 newuser->groups = strdup(args[cur_arg + 1]);
4190 cur_arg += 2;
4191 continue;
4192 } else {
4193 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4194 file, linenum, args[0]);
4195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
4197 }
4198 }
4199 } else {
4200 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4201 err_code |= ERR_ALERT | ERR_FATAL;
4202 }
4203
4204out:
4205 return err_code;
4206}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207
4208/*
4209 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004210 * Returns the error code, 0 if OK, or any combination of :
4211 * - ERR_ABORT: must abort ASAP
4212 * - ERR_FATAL: we can continue parsing but not start the service
4213 * - ERR_WARN: a warning has been emitted
4214 * - ERR_ALERT: an alert has been emitted
4215 * Only the two first ones can stop processing, the two others are just
4216 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004218int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004220 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 FILE *f;
4222 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004224 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 if ((f=fopen(file,"r")) == NULL)
4227 return -1;
4228
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004229 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004230 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004231 char *end;
4232 char *args[MAX_LINE_ARGS + 1];
4233 char *line = thisline;
4234
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 linenum++;
4236
4237 end = line + strlen(line);
4238
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004239 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4240 /* Check if we reached the limit and the last char is not \n.
4241 * Watch out for the last line without the terminating '\n'!
4242 */
4243 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004244 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004246 }
4247
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004249 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 line++;
4251
4252 arg = 0;
4253 args[arg] = line;
4254
4255 while (*line && arg < MAX_LINE_ARGS) {
4256 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4257 * C equivalent value. Other combinations left unchanged (eg: \1).
4258 */
4259 if (*line == '\\') {
4260 int skip = 0;
4261 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4262 *line = line[1];
4263 skip = 1;
4264 }
4265 else if (line[1] == 'r') {
4266 *line = '\r';
4267 skip = 1;
4268 }
4269 else if (line[1] == 'n') {
4270 *line = '\n';
4271 skip = 1;
4272 }
4273 else if (line[1] == 't') {
4274 *line = '\t';
4275 skip = 1;
4276 }
4277 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004278 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 unsigned char hex1, hex2;
4280 hex1 = toupper(line[2]) - '0';
4281 hex2 = toupper(line[3]) - '0';
4282 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4283 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4284 *line = (hex1<<4) + hex2;
4285 skip = 3;
4286 }
4287 else {
4288 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 }
4291 }
4292 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004293 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 end -= skip;
4295 }
4296 line++;
4297 }
4298 else if (*line == '#' || *line == '\n' || *line == '\r') {
4299 /* end of string, end of loop */
4300 *line = 0;
4301 break;
4302 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004303 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004305 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004306 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 line++;
4308 args[++arg] = line;
4309 }
4310 else {
4311 line++;
4312 }
4313 }
4314
4315 /* empty line */
4316 if (!**args)
4317 continue;
4318
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004319 if (*line) {
4320 /* we had to stop due to too many args.
4321 * Let's terminate the string, print the offending part then cut the
4322 * last arg.
4323 */
4324 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4325 line++;
4326 *line = '\0';
4327
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004328 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004329 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 args[arg] = line;
4332 }
4333
Willy Tarreau540abe42007-05-02 20:50:16 +02004334 /* zero out remaining args and ensure that at least one entry
4335 * is zeroed out.
4336 */
4337 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 args[arg] = line;
4339 }
4340
Willy Tarreau3842f002009-06-14 11:39:52 +02004341 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004342 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004343 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004344 for (arg=0; *args[arg+1]; arg++)
4345 args[arg] = args[arg+1]; // shift args after inversion
4346 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004347 else if (!strcmp(args[0], "default")) {
4348 kwm = KWM_DEF;
4349 for (arg=0; *args[arg+1]; arg++)
4350 args[arg] = args[arg+1]; // shift args after inversion
4351 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004352
Willy Tarreau3842f002009-06-14 11:39:52 +02004353 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4354 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004355 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004356 }
4357
Willy Tarreau977b8e42006-12-29 14:19:17 +01004358 if (!strcmp(args[0], "listen") ||
4359 !strcmp(args[0], "frontend") ||
4360 !strcmp(args[0], "backend") ||
4361 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004362 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004364 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004365 cursection = strdup(args[0]);
4366 }
4367 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004369 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004370 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004371 } else if (!strcmp(args[0], "userlist")) {
4372 confsect = CFG_USERLIST;
4373 free(cursection);
4374 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004375 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 /* else it's a section keyword */
4377
4378 switch (confsect) {
4379 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 break;
4382 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004383 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004385 case CFG_USERLIST:
4386 err_code |= cfg_parse_users(file, linenum, args, kwm);
4387 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004389 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004392
4393 if (err_code & ERR_ABORT)
4394 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004396 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004397 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004399 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004400}
4401
Willy Tarreaubb925012009-07-23 13:36:36 +02004402/*
4403 * Returns the error code, 0 if OK, or any combination of :
4404 * - ERR_ABORT: must abort ASAP
4405 * - ERR_FATAL: we can continue parsing but not start the service
4406 * - ERR_WARN: a warning has been emitted
4407 * - ERR_ALERT: an alert has been emitted
4408 * Only the two first ones can stop processing, the two others are just
4409 * indicators.
4410 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004411int check_config_validity()
4412{
4413 int cfgerr = 0;
4414 struct proxy *curproxy = NULL;
4415 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004416 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004417 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004418 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419
4420 /*
4421 * Now, check for the integrity of all that we have collected.
4422 */
4423
4424 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004425 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004427 /* first, we will invert the proxy list order */
4428 curproxy = NULL;
4429 while (proxy) {
4430 struct proxy *next;
4431
4432 next = proxy->next;
4433 proxy->next = curproxy;
4434 curproxy = proxy;
4435 if (!next)
4436 break;
4437 proxy = next;
4438 }
4439
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004441 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 }
4445
4446 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004447 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004448 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004449 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004450 unsigned int next_id;
4451
4452 if (!curproxy->uuid) {
4453 /* proxy ID not set, use automatic numbering with first
4454 * spare entry starting with next_pxid.
4455 */
4456 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4457 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4458 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4459 next_pxid++;
4460 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004461
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004463 /* ensure we don't keep listeners uselessly bound */
4464 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 curproxy = curproxy->next;
4466 continue;
4467 }
4468
Willy Tarreauff01a212009-03-15 13:46:16 +01004469 switch (curproxy->mode) {
4470 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004471 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004472 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004473 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4474 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004475 cfgerr++;
4476 }
4477
4478 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004479 Warning("config : servers will be ignored for %s '%s'.\n",
4480 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004481 break;
4482
4483 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004484 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004485 break;
4486
4487 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004488 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004489 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004490 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4491 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004492 cfgerr++;
4493 }
4494 break;
4495 }
4496
4497 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004498 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4499 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 cfgerr++;
4501 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004502
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004503 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004504 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004505 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004506 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004508 cfgerr++;
4509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004511 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004512 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4513 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004514 cfgerr++;
4515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004517 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004518 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4519 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004520 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004521 }
4522 }
4523 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4524 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4525 /* If no LB algo is set in a backend, and we're not in
4526 * transparent mode, dispatch mode nor proxy mode, we
4527 * want to use balance roundrobin by default.
4528 */
4529 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4530 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 }
4532 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004533
Willy Tarreau82936582007-11-30 15:20:09 +01004534 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4535 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004536 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4537 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004538 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004539 }
4540
Willy Tarreauef781042010-01-27 11:53:01 +01004541 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4542 curproxy->options &= ~PR_O2_CHK_SNDST;
4543 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4544 "send-state", proxy_type_str(curproxy), curproxy->id);
4545 err_code |= ERR_WARN;
4546 }
4547
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004548 /* if a default backend was specified, let's find it */
4549 if (curproxy->defbe.name) {
4550 struct proxy *target;
4551
Alex Williams96532db2009-11-01 21:27:13 -05004552 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004553 if (!target) {
4554 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4555 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004556 cfgerr++;
4557 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004558 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4559 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004560 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004561 } else {
4562 free(curproxy->defbe.name);
4563 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004564 /* we force the backend to be present on at least all of
4565 * the frontend's processes.
4566 */
4567 target->bind_proc = curproxy->bind_proc ?
4568 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
4570 }
4571
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004572 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004573 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4574 /* map jump target for ACT_SETBE in req_rep chain */
4575 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004576 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004577 struct proxy *target;
4578
Willy Tarreaua496b602006-12-17 23:15:24 +01004579 if (exp->action != ACT_SETBE)
4580 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004581
Alex Williams96532db2009-11-01 21:27:13 -05004582 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004583 if (!target) {
4584 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4585 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004586 cfgerr++;
4587 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004588 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4589 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004590 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004591 } else {
4592 free((void *)exp->replace);
4593 exp->replace = (const char *)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 Tarreaua496b602006-12-17 23:15:24 +01004599 }
4600 }
4601 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004602
4603 /* find the target proxy for 'use_backend' rules */
4604 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004605 struct proxy *target;
4606
Alex Williams96532db2009-11-01 21:27:13 -05004607 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004608
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004609 if (!target) {
4610 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4611 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004612 cfgerr++;
4613 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004614 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4615 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004616 cfgerr++;
4617 } else {
4618 free((void *)rule->be.name);
4619 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004620 /* we force the backend to be present on at least all of
4621 * the frontend's processes.
4622 */
4623 target->bind_proc = curproxy->bind_proc ?
4624 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004625 }
4626 }
4627
Emeric Brunb982a3d2010-01-04 15:45:53 +01004628 /* find the target table for 'stick' rules */
4629 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4630 struct proxy *target;
4631
Emeric Brun1d33b292010-01-04 15:47:17 +01004632 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4633 if (mrule->flags & STK_IS_STORE)
4634 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4635
Emeric Brunb982a3d2010-01-04 15:45:53 +01004636 if (mrule->table.name)
4637 target = findproxy(mrule->table.name, PR_CAP_BE);
4638 else
4639 target = curproxy;
4640
4641 if (!target) {
4642 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4643 curproxy->id, mrule->table.name);
4644 cfgerr++;
4645 }
4646 else if (target->table.size == 0) {
4647 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4648 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4649 cfgerr++;
4650 }
4651 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4652 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4653 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4654 cfgerr++;
4655 }
4656 else {
4657 free((void *)mrule->table.name);
4658 mrule->table.t = &(target->table);
4659 }
4660 }
4661
4662 /* find the target table for 'store response' rules */
4663 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4664 struct proxy *target;
4665
Emeric Brun1d33b292010-01-04 15:47:17 +01004666 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4667
Emeric Brunb982a3d2010-01-04 15:45:53 +01004668 if (mrule->table.name)
4669 target = findproxy(mrule->table.name, PR_CAP_BE);
4670 else
4671 target = curproxy;
4672
4673 if (!target) {
4674 Alert("Proxy '%s': unable to find store table '%s'.\n",
4675 curproxy->id, mrule->table.name);
4676 cfgerr++;
4677 }
4678 else if (target->table.size == 0) {
4679 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4680 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4681 cfgerr++;
4682 }
4683 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4684 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4685 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4686 cfgerr++;
4687 }
4688 else {
4689 free((void *)mrule->table.name);
4690 mrule->table.t = &(target->table);
4691 }
4692 }
4693
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004694 cfgerr += acl_find_targets(curproxy);
4695
Willy Tarreau2738a142006-07-08 17:28:09 +02004696 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004697 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004698 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004699 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004700 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004701 " | While not properly invalid, you will certainly encounter various problems\n"
4702 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004703 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004704 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004705 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004706 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004707
Willy Tarreau1fa31262007-12-03 00:36:16 +01004708 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4709 * We must still support older configurations, so let's find out whether those
4710 * parameters have been set or must be copied from contimeouts.
4711 */
4712 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004713 if (!curproxy->timeout.tarpit ||
4714 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004715 /* tarpit timeout not set. We search in the following order:
4716 * default.tarpit, curr.connect, default.connect.
4717 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004718 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004719 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004720 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004721 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004722 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004723 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004724 }
4725 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004726 (!curproxy->timeout.queue ||
4727 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004728 /* queue timeout not set. We search in the following order:
4729 * default.queue, curr.connect, default.connect.
4730 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004731 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004732 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004733 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004734 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004735 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004736 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004737 }
4738 }
4739
Willy Tarreauf3c69202006-07-09 16:42:34 +02004740 if (curproxy->options & PR_O_SSL3_CHK) {
4741 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4742 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4743 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4744 }
4745
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004746 /* The small pools required for the capture lists */
4747 if (curproxy->nb_req_cap)
4748 curproxy->req_cap_pool = create_pool("ptrcap",
4749 curproxy->nb_req_cap * sizeof(char *),
4750 MEM_F_SHARED);
4751 if (curproxy->nb_rsp_cap)
4752 curproxy->rsp_cap_pool = create_pool("ptrcap",
4753 curproxy->nb_rsp_cap * sizeof(char *),
4754 MEM_F_SHARED);
4755
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004756 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4757 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4758 MEM_F_SHARED);
4759
Willy Tarreau86034312006-12-29 00:10:33 +01004760 /* for backwards compatibility with "listen" instances, if
4761 * fullconn is not set but maxconn is set, then maxconn
4762 * is used.
4763 */
4764 if (!curproxy->fullconn)
4765 curproxy->fullconn = curproxy->maxconn;
4766
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 /* first, we will invert the servers list order */
4768 newsrv = NULL;
4769 while (curproxy->srv) {
4770 struct server *next;
4771
4772 next = curproxy->srv->next;
4773 curproxy->srv->next = newsrv;
4774 newsrv = curproxy->srv;
4775 if (!next)
4776 break;
4777 curproxy->srv = next;
4778 }
4779
Willy Tarreau20697042007-11-15 23:26:18 +01004780 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004781 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004783 /* We have to initialize the server lookup mechanism depending
4784 * on what LB algorithm was choosen.
4785 */
4786
4787 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4788 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4789 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004790 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4791 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4792 init_server_map(curproxy);
4793 } else {
4794 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4795 fwrr_init_server_groups(curproxy);
4796 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004797 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004798
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004799 case BE_LB_KIND_LC:
4800 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004801 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004802 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004803
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004804 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004805 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4806 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4807 chash_init_server_tree(curproxy);
4808 } else {
4809 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4810 init_server_map(curproxy);
4811 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004812 break;
4813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814
4815 if (curproxy->options & PR_O_LOGASAP)
4816 curproxy->to_log &= ~LW_BYTES;
4817
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004818 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4819 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4820 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4821 proxy_type_str(curproxy), curproxy->id);
4822 err_code |= ERR_WARN;
4823 }
4824
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004826 * ensure that we're not cross-dressing a TCP server into HTTP.
4827 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004828 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004829 newsrv = curproxy->srv;
4830 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004831 if (!newsrv->puid) {
4832 /* server ID not set, use automatic numbering with first
4833 * spare entry starting with next_svid.
4834 */
4835 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4836 newsrv->conf.id.key = newsrv->puid = next_id;
4837 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4838 next_id++;
4839 }
4840
Willy Tarreau21d2af32008-02-14 20:25:24 +01004841 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004842 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4843 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004844 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004845 }
4846 newsrv = newsrv->next;
4847 }
4848
4849 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 * If this server supports a maxconn parameter, it needs a dedicated
4851 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004852 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 */
4854 newsrv = curproxy->srv;
4855 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004856 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 /* Only 'minconn' was specified, or it was higher than or equal
4858 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4859 * this will avoid further useless expensive computations.
4860 */
4861 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004862 } else if (newsrv->maxconn && !newsrv->minconn) {
4863 /* minconn was not specified, so we set it to maxconn */
4864 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004865 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004866 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4867 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004868 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
4870
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004871 if (newsrv->trackit) {
4872 struct proxy *px;
4873 struct server *srv;
4874 char *pname, *sname;
4875
4876 pname = newsrv->trackit;
4877 sname = strrchr(pname, '/');
4878
4879 if (sname)
4880 *sname++ = '\0';
4881 else {
4882 sname = pname;
4883 pname = NULL;
4884 }
4885
4886 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004887 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004888 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004889 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4890 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004891 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004892 cfgerr++;
4893 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004894 }
4895 } else
4896 px = curproxy;
4897
4898 srv = findserver(px, sname);
4899 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004900 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4901 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004902 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004903 cfgerr++;
4904 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004905 }
4906
4907 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004908 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004909 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004910 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004911 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004912 cfgerr++;
4913 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004914 }
4915
4916 if (curproxy != px &&
4917 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004918 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01004919 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004920 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004921 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004922 cfgerr++;
4923 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004924 }
4925
4926 newsrv->tracked = srv;
4927 newsrv->tracknext = srv->tracknext;
4928 srv->tracknext = newsrv;
4929
4930 free(newsrv->trackit);
4931 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004932 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 newsrv = newsrv->next;
4934 }
4935
Willy Tarreauc1a21672009-08-16 22:37:44 +02004936 if (curproxy->cap & PR_CAP_FE) {
4937 if (curproxy->tcp_req.inspect_delay ||
4938 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4939 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4940
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004941 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004942 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004943 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004944 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004945
4946 /* both TCP and HTTP must check switching rules */
4947 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4948 }
4949
4950 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004951 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004952 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004953 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004954 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004955
Emeric Brunb982a3d2010-01-04 15:45:53 +01004956 /* init table on backend capabilities proxy */
4957 stktable_init(&curproxy->table);
4958
Willy Tarreauc1a21672009-08-16 22:37:44 +02004959 /* If the backend does requires RDP cookie persistence, we have to
4960 * enable the corresponding analyser.
4961 */
4962 if (curproxy->options2 & PR_O2_RDPC_PRST)
4963 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4964 }
4965
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004966 listener = NULL;
4967 while (curproxy->listen) {
4968 struct listener *next;
4969
4970 next = curproxy->listen->next;
4971 curproxy->listen->next = listener;
4972 listener = curproxy->listen;
4973
4974 if (!next)
4975 break;
4976
4977 curproxy->listen = next;
4978 }
4979
Willy Tarreaue6b98942007-10-29 01:09:36 +01004980 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004981 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004982 listener = curproxy->listen;
4983 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004984 if (!listener->luid) {
4985 /* listener ID not set, use automatic numbering with first
4986 * spare entry starting with next_luid.
4987 */
4988 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4989 listener->conf.id.key = listener->luid = next_id;
4990 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4991 next_id++;
4992 }
4993
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004994 /* enable separate counters */
4995 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4996 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4997 if (!listener->name) {
4998 sprintf(trash, "sock-%d", listener->luid);
4999 listener->name = strdup(trash);
5000 }
5001 }
5002
Willy Tarreaue6b98942007-10-29 01:09:36 +01005003 if (curproxy->options & PR_O_TCP_NOLING)
5004 listener->options |= LI_O_NOLINGER;
5005 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005006 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005007 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005008 listener->accept = event_accept;
5009 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005010 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005011 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005012
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005013 /* smart accept mode is automatic in HTTP mode */
5014 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5015 (curproxy->mode == PR_MODE_HTTP &&
5016 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5017 listener->options |= LI_O_NOQUICKACK;
5018
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005019 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005020 listener = listener->next;
5021 }
5022
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 curproxy = curproxy->next;
5024 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005025
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005026 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5027 struct auth_users *curuser;
5028 int g;
5029
5030 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5031 unsigned int group_mask = 0;
5032 char *group = NULL;
5033
5034 if (!curuser->groups)
5035 continue;
5036
5037 while ((group = strtok(group?NULL:curuser->groups, ","))) {
5038
5039 for (g = 0; g < curuserlist->grpcnt; g++)
5040 if (!strcmp(curuserlist->groups[g], group))
5041 break;
5042
5043 if (g == curuserlist->grpcnt) {
5044 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5045 curuserlist->name, group, curuser->user);
5046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
5048 }
5049
5050 group_mask |= (1 << g);
5051 }
5052
5053 free(curuser->groups);
5054 curuser->group_mask = group_mask;
5055 }
5056
5057 for (g = 0; g < curuserlist->grpcnt; g++) {
5058 char *user = NULL;
5059
5060 if (!curuserlist->groupusers[g])
5061 continue;
5062
5063 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5064 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5065 if (!strcmp(curuser->user, user))
5066 break;
5067
5068 if (!curuser) {
5069 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5070 curuserlist->name, user, curuserlist->groups[g]);
5071 err_code |= ERR_ALERT | ERR_FATAL;
5072 goto out;
5073 }
5074
5075 curuser->group_mask |= (1 << g);
5076 }
5077
5078 free(curuserlist->groupusers[g]);
5079 }
5080
5081 free(curuserlist->groupusers);
5082
5083#ifdef DEBUG_AUTH
5084 for (g = 0; g < curuserlist->grpcnt; g++) {
5085 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5086
5087 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5088 if (curuser->group_mask & (1 << g))
5089 fprintf(stderr, " %s", curuser->user);
5090 }
5091
5092 fprintf(stderr, "\n");
5093 }
5094#endif
5095
5096 }
5097
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005098 /*
5099 * Recount currently required checks.
5100 */
5101
5102 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5103 int optnum;
5104
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005105 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5106 if (curproxy->options & cfg_opts[optnum].val)
5107 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005108
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005109 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5110 if (curproxy->options2 & cfg_opts2[optnum].val)
5111 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005112 }
5113
Willy Tarreaubb925012009-07-23 13:36:36 +02005114 if (cfgerr > 0)
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 out:
5117 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118}
5119
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005120/*
5121 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5122 * parsing sessions.
5123 */
5124void cfg_register_keywords(struct cfg_kw_list *kwl)
5125{
5126 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5127}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005129/*
5130 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5131 */
5132void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5133{
5134 LIST_DEL(&kwl->list);
5135 LIST_INIT(&kwl->list);
5136}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137
5138/*
5139 * Local variables:
5140 * c-indent-level: 8
5141 * c-basic-offset: 8
5142 * End:
5143 */