blob: 147f0185bb7b4372354168f3abd83ffc3bcefb43 [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];
Willy Tarreau88e05812010-03-03 00:16:00 +0100730 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
731 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200732 break;
733 }
734
735 if (!i || args[1][i]) {
736 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
737 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742
743 if (global.node)
744 free(global.node);
745
746 global.node = strdup(args[1]);
747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 else if (!strcmp(args[0], "pidfile")) {
749 if (global.pidfile != NULL) {
750 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT;
752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 }
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 global.pidfile = strdup(args[1]);
760 }
761 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100762 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200763 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764
765 if (*(args[1]) == 0 || *(args[2]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770
771 facility = get_log_facility(args[2]);
772 if (facility < 0) {
773 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777
778 level = 7; /* max syslog level = debug */
779 if (*(args[3])) {
780 level = get_log_level(args[3]);
781 if (level < 0) {
782 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT | ERR_FATAL;
784 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
786 }
787
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200788 minlvl = 0; /* limit syslog level to this level (emerg) */
789 if (*(args[4])) {
790 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200792 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
794 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200795 }
796 }
797
Robert Tsai81ae1952007-12-05 10:47:29 +0100798 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100799 struct sockaddr_un *sk = str2sun(args[1]);
800 if (!sk) {
801 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
802 args[1], (int)sizeof(sk->sun_path) - 1);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100807 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100809 struct sockaddr_in *sk = str2sa(args[1]);
810 if (!sk) {
811 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100816 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100817 if (!logsrv.u.in.sin_port)
818 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820
821 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100822 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 global.logfac1 = facility;
824 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200825 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100828 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 global.logfac2 = facility;
830 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200831 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 else {
834 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200837 }
838 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
839 if (global.spread_checks != 0) {
840 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT;
842 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200848 }
849 global.spread_checks = atol(args[1]);
850 if (global.spread_checks < 0 || global.spread_checks > 50) {
851 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200852 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 }
855 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 struct cfg_kw_list *kwl;
857 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200858 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200859
860 list_for_each_entry(kwl, &cfg_keywords.list, list) {
861 for (index = 0; kwl->kw[index].kw != NULL; index++) {
862 if (kwl->kw[index].section != CFG_GLOBAL)
863 continue;
864 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
865 /* prepare error message just in case */
866 snprintf(trash, sizeof(trash),
867 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200868 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
869 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200870 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200871 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200872 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200873 else if (rc > 0) {
874 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200875 err_code |= ERR_WARN;
876 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200877 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200879 }
880 }
881 }
882
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200886
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 out:
888 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
Willy Tarreau97cb7802010-01-03 20:23:58 +0100891/* Perform the most basic initialization of a proxy :
892 * memset(), list_init(*), reset_timeouts(*).
893 */
894static void init_new_proxy(struct proxy *p)
895{
896 memset(p, 0, sizeof(struct proxy));
897 LIST_INIT(&p->pendconns);
898 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100899 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100900 LIST_INIT(&p->block_cond);
901 LIST_INIT(&p->redirect_rules);
902 LIST_INIT(&p->mon_fail_cond);
903 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100904 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100905 LIST_INIT(&p->sticking_rules);
906 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100907 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100908 LIST_INIT(&p->req_add);
909 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100910
911 /* Timeouts are defined as -1 */
912 proxy_reset_timeouts(p);
913}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200915void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100917 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 defproxy.mode = PR_MODE_TCP;
919 defproxy.state = PR_STNEW;
920 defproxy.maxconn = cfg_maxpconn;
921 defproxy.conn_retries = CONN_RETRIES;
922 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100923
924 defproxy.defsrv.inter = DEF_CHKINTR;
925 defproxy.defsrv.fastinter = 0;
926 defproxy.defsrv.downinter = 0;
927 defproxy.defsrv.rise = DEF_RISETIME;
928 defproxy.defsrv.fall = DEF_FALLTIME;
929 defproxy.defsrv.check_port = 0;
930 defproxy.defsrv.maxqueue = 0;
931 defproxy.defsrv.minconn = 0;
932 defproxy.defsrv.maxconn = 0;
933 defproxy.defsrv.slowstart = 0;
934 defproxy.defsrv.onerror = DEF_HANA_ONERR;
935 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
936 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937}
938
Willy Tarreauade5ec42010-01-28 19:33:49 +0100939
940static int create_cond_regex_rule(const char *file, int line,
941 struct proxy *px, int dir, int action, int flags,
942 const char *cmd, const char *reg, const char *repl,
943 const char **cond_start)
944{
945 regex_t *preg = NULL;
946 const char *err;
947 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100948 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100949
950 if (px == &defproxy) {
951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto err;
954 }
955
956 if (*reg == 0) {
957 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto err;
960 }
961
962 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
963 err_code |= ERR_WARN;
964
Willy Tarreau5321c422010-01-28 20:35:13 +0100965 if (cond_start &&
966 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
967 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
968 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
969 file, line, cmd);
970 err_code |= ERR_ALERT | ERR_FATAL;
971 goto err;
972 }
973 }
974 else if (cond_start && **cond_start) {
975 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
976 file, line, cmd, *cond_start);
977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto err;
979 }
980
981 if (dir == ACL_DIR_REQ)
982 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100983 else
984 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100985
Willy Tarreauade5ec42010-01-28 19:33:49 +0100986 preg = calloc(1, sizeof(regex_t));
987 if (!preg) {
988 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
989 err_code = ERR_ALERT | ERR_FATAL;
990 goto err;
991 }
992
993 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
994 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
995 err_code = ERR_ALERT | ERR_FATAL;
996 goto err;
997 }
998
999 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001000 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001001 if (repl && err) {
1002 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1003 file, line, cmd, *err);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto err;
1006 }
1007
1008 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1009 err_code |= ERR_WARN;
1010
1011 return err_code;
1012 err:
1013 free(preg);
1014 return err_code;
1015}
1016
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001019 * Returns the error code, 0 if OK, or any combination of :
1020 * - ERR_ABORT: must abort ASAP
1021 * - ERR_FATAL: we can continue parsing but not start the service
1022 * - ERR_WARN: a warning has been emitted
1023 * - ERR_ALERT: an alert has been emitted
1024 * Only the two first ones can stop processing, the two others are just
1025 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001027int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028{
1029 static struct proxy *curproxy = NULL;
1030 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001031 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001032 int rc;
1033 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001034 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001035 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036
Willy Tarreau977b8e42006-12-29 14:19:17 +01001037 if (!strcmp(args[0], "listen"))
1038 rc = PR_CAP_LISTEN;
1039 else if (!strcmp(args[0], "frontend"))
1040 rc = PR_CAP_FE | PR_CAP_RS;
1041 else if (!strcmp(args[0], "backend"))
1042 rc = PR_CAP_BE | PR_CAP_RS;
1043 else if (!strcmp(args[0], "ruleset"))
1044 rc = PR_CAP_RS;
1045 else
1046 rc = PR_CAP_NONE;
1047
1048 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (!*args[1]) {
1050 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1051 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001053 err_code |= ERR_ALERT | ERR_ABORT;
1054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001056
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001057 err = invalid_char(args[1]);
1058 if (err) {
1059 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1060 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001062 }
1063
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001064 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1065 /*
1066 * If there are two proxies with the same name only following
1067 * combinations are allowed:
1068 *
1069 * listen backend frontend ruleset
1070 * listen - - - -
1071 * backend - - OK -
1072 * frontend - OK - -
1073 * ruleset - - - -
1074 */
1075
1076 if (!strcmp(curproxy->id, args[1]) &&
1077 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1078 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001079 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1080 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1081 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001082 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001083 }
1084 }
1085
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1087 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001088 err_code |= ERR_ALERT | ERR_ABORT;
1089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001091
Willy Tarreau97cb7802010-01-03 20:23:58 +01001092 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 curproxy->next = proxy;
1094 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001095 curproxy->conf.file = file;
1096 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001097 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001099 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100
1101 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001102 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001103 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001104 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001105 err_code |= ERR_FATAL;
1106 goto out;
1107 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 new = curproxy->listen;
1109 while (new != last) {
1110 new->conf.file = file;
1111 new->conf.line = linenum;
1112 new = new->next;
1113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 global.maxsock++;
1115 }
1116
1117 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001118 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001122 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001123 curproxy->no_options = defproxy.no_options;
1124 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001125 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001126 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001127 curproxy->except_net = defproxy.except_net;
1128 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001129 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001130 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001132 if (defproxy.fwdfor_hdr_len) {
1133 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1134 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1135 }
1136
Willy Tarreaub86db342009-11-30 11:50:16 +01001137 if (defproxy.orgto_hdr_len) {
1138 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1139 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1140 }
1141
Willy Tarreau977b8e42006-12-29 14:19:17 +01001142 if (curproxy->cap & PR_CAP_FE) {
1143 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001144 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001145 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146
1147 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001148 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1149 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150
1151 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153
Willy Tarreau977b8e42006-12-29 14:19:17 +01001154 if (curproxy->cap & PR_CAP_BE) {
1155 curproxy->fullconn = defproxy.fullconn;
1156 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157
Willy Tarreau977b8e42006-12-29 14:19:17 +01001158 if (defproxy.check_req)
1159 curproxy->check_req = strdup(defproxy.check_req);
1160 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161
Willy Tarreau977b8e42006-12-29 14:19:17 +01001162 if (defproxy.cookie_name)
1163 curproxy->cookie_name = strdup(defproxy.cookie_name);
1164 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001165 if (defproxy.cookie_domain)
1166 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001167
Emeric Brun647caf12009-06-30 17:57:00 +02001168 if (defproxy.rdp_cookie_name)
1169 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1170 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1171
Willy Tarreau01732802007-11-01 22:48:15 +01001172 if (defproxy.url_param_name)
1173 curproxy->url_param_name = strdup(defproxy.url_param_name);
1174 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001175
Benoitaffb4812009-03-25 13:02:10 +01001176 if (defproxy.hh_name)
1177 curproxy->hh_name = strdup(defproxy.hh_name);
1178 curproxy->hh_len = defproxy.hh_len;
1179 curproxy->hh_match_domain = defproxy.hh_match_domain;
1180
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001181 if (defproxy.iface_name)
1182 curproxy->iface_name = strdup(defproxy.iface_name);
1183 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001186 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 if (defproxy.capture_name)
1188 curproxy->capture_name = strdup(defproxy.capture_name);
1189 curproxy->capture_namelen = defproxy.capture_namelen;
1190 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192
Willy Tarreau977b8e42006-12-29 14:19:17 +01001193 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001194 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001195 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001196 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001197 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 curproxy->uri_auth = defproxy.uri_auth;
1199 curproxy->mon_net = defproxy.mon_net;
1200 curproxy->mon_mask = defproxy.mon_mask;
1201 if (defproxy.monitor_uri)
1202 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1203 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001204 if (defproxy.defbe.name)
1205 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001206 }
1207
1208 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001209 curproxy->timeout.connect = defproxy.timeout.connect;
1210 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001211 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001212 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001213 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001214 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001215 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001216 curproxy->source_addr = defproxy.source_addr;
1217 }
1218
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 curproxy->mode = defproxy.mode;
1220 curproxy->logfac1 = defproxy.logfac1;
1221 curproxy->logsrv1 = defproxy.logsrv1;
1222 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001223 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->logfac2 = defproxy.logfac2;
1225 curproxy->logsrv2 = defproxy.logsrv2;
1226 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001229 curproxy->conf.used_listener_id = EB_ROOT;
1230 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001231
Willy Tarreau93893792009-07-23 13:19:11 +02001232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1235 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001236 /* FIXME-20070101: we should do this too at the end of the
1237 * config parsing to free all default values.
1238 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001239 free(defproxy.check_req);
1240 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001241 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001242 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001243 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001244 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001245 free(defproxy.capture_name);
1246 free(defproxy.monitor_uri);
1247 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001248 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001249 free(defproxy.fwdfor_hdr_name);
1250 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001251 free(defproxy.orgto_hdr_name);
1252 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001253
Willy Tarreaua534fea2008-08-03 12:19:50 +02001254 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001255 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001256
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 /* we cannot free uri_auth because it might already be used */
1258 init_default_instance();
1259 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001260 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 }
1263 else if (curproxy == NULL) {
1264 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268
Willy Tarreau977b8e42006-12-29 14:19:17 +01001269
1270 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001272 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001273 int cur_arg;
1274
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 if (curproxy == &defproxy) {
1276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001281 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282
1283 if (strchr(args[1], ':') == NULL) {
1284 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001289
1290 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001291 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001295
Willy Tarreau90a570f2009-10-04 20:54:54 +02001296 new_listen = curproxy->listen;
1297 while (new_listen != last_listen) {
1298 new_listen->conf.file = file;
1299 new_listen->conf.line = linenum;
1300 new_listen = new_listen->next;
1301 }
1302
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001303 cur_arg = 2;
1304 while (*(args[cur_arg])) {
1305 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1306#ifdef SO_BINDTODEVICE
1307 struct listener *l;
1308
1309 if (!*args[cur_arg + 1]) {
1310 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1311 file, linenum, args[0]);
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 }
1315
1316 for (l = curproxy->listen; l != last_listen; l = l->next)
1317 l->interface = strdup(args[cur_arg + 1]);
1318
1319 global.last_checks |= LSTCHK_NETADM;
1320
1321 cur_arg += 2;
1322 continue;
1323#else
1324 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1325 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001328#endif
1329 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001330 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1331#ifdef TCP_MAXSEG
1332 struct listener *l;
1333 int mss;
1334
1335 if (!*args[cur_arg + 1]) {
1336 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001340 }
1341
1342 mss = str2uic(args[cur_arg + 1]);
1343 if (mss < 1 || mss > 65535) {
1344 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001348 }
1349
1350 for (l = curproxy->listen; l != last_listen; l = l->next)
1351 l->maxseg = mss;
1352
1353 cur_arg += 2;
1354 continue;
1355#else
1356 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1357 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001358 err_code |= ERR_ALERT | ERR_FATAL;
1359 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001360#endif
1361 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001362
1363 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1364#ifdef TCP_DEFER_ACCEPT
1365 struct listener *l;
1366
1367 for (l = curproxy->listen; l != last_listen; l = l->next)
1368 l->options |= LI_O_DEF_ACCEPT;
1369
1370 cur_arg ++;
1371 continue;
1372#else
1373 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1374 file, linenum, args[0], args[cur_arg]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377#endif
1378 }
1379
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001382 struct listener *l;
1383
1384 for (l = curproxy->listen; l != last_listen; l = l->next)
1385 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001386
1387 cur_arg ++;
1388 continue;
1389#else
1390 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1391 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001394#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001395 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001396
1397 if (!strcmp(args[cur_arg], "name")) {
1398 struct listener *l;
1399
1400 for (l = curproxy->listen; l != last_listen; l = l->next)
1401 l->name = strdup(args[cur_arg + 1]);
1402
1403 cur_arg += 2;
1404 continue;
1405 }
1406
1407 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001408 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001409 struct listener *l;
1410
1411 if (curproxy->listen->next != last_listen) {
1412 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1413 file, linenum, args[cur_arg]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
1416 }
1417
1418 if (!*args[cur_arg + 1]) {
1419 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1420 file, linenum, args[cur_arg]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424
1425 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001426 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001427
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001428 if (curproxy->listen->luid <= 0) {
1429 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001430 file, linenum);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433 }
1434
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001435 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1436 if (node) {
1437 l = container_of(node, struct listener, conf.id);
1438 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1439 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
1442 }
1443 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1444
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001445 cur_arg += 2;
1446 continue;
1447 }
1448
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001449 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 +01001450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
1457 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1458 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1459 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 /* flush useless bits */
1468 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001471 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 if (!*args[1]) {
1476 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001480 }
1481
Willy Tarreaua534fea2008-08-03 12:19:50 +02001482 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001483 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001484 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001485 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001486 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1487
Willy Tarreau93893792009-07-23 13:19:11 +02001488 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1491 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1492 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1493 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1494 else {
1495 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 }
1499 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001500 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001501 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001502
1503 if (curproxy == &defproxy) {
1504 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 }
1509
1510 if (!*args[1]) {
1511 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_ALERT | ERR_FATAL;
1514 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001515 }
1516
1517 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001518 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001519
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001520 if (curproxy->uuid <= 0) {
1521 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001525 }
1526
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001527 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1528 if (node) {
1529 struct proxy *target = container_of(node, struct proxy, conf.id);
1530 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1531 file, linenum, proxy_type_str(curproxy), curproxy->id,
1532 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
1535 }
1536 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001537 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001538 else if (!strcmp(args[0], "description")) {
1539 int i, len=0;
1540 char *d;
1541
Cyril Bonté99ed3272010-01-24 23:29:44 +01001542 if (curproxy == &defproxy) {
1543 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1544 file, linenum, args[0]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001549 if (!*args[1]) {
1550 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1551 file, linenum, args[0]);
1552 return -1;
1553 }
1554
1555 for(i=1; *args[i]; i++)
1556 len += strlen(args[i])+1;
1557
1558 d = (char *)calloc(1, len);
1559 curproxy->desc = d;
1560
1561 d += sprintf(d, "%s", args[1]);
1562 for(i=2; *args[i]; i++)
1563 d += sprintf(d, " %s", args[i]);
1564
1565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1567 curproxy->state = PR_STSTOPPED;
1568 }
1569 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1570 curproxy->state = PR_STNEW;
1571 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001572 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1573 int cur_arg = 1;
1574 unsigned int set = 0;
1575
1576 while (*args[cur_arg]) {
1577 int u;
1578 if (strcmp(args[cur_arg], "all") == 0) {
1579 set = 0;
1580 break;
1581 }
1582 else if (strcmp(args[cur_arg], "odd") == 0) {
1583 set |= 0x55555555;
1584 }
1585 else if (strcmp(args[cur_arg], "even") == 0) {
1586 set |= 0xAAAAAAAA;
1587 }
1588 else {
1589 u = str2uic(args[cur_arg]);
1590 if (u < 1 || u > 32) {
1591 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001595 }
1596 if (u > global.nbproc) {
1597 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001600 }
1601 set |= 1 << (u - 1);
1602 }
1603 cur_arg++;
1604 }
1605 curproxy->bind_proc = set;
1606 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001612 }
1613
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001614 err = invalid_char(args[1]);
1615 if (err) {
1616 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1617 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001619 }
1620
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001621 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1622 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1623 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001626 }
1627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1629 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (*(args[1]) == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001640
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001641 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001642 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 curproxy->cookie_name = strdup(args[1]);
1644 curproxy->cookie_len = strlen(curproxy->cookie_name);
1645
1646 cur_arg = 2;
1647 while (*(args[cur_arg])) {
1648 if (!strcmp(args[cur_arg], "rewrite")) {
1649 curproxy->options |= PR_O_COOK_RW;
1650 }
1651 else if (!strcmp(args[cur_arg], "indirect")) {
1652 curproxy->options |= PR_O_COOK_IND;
1653 }
1654 else if (!strcmp(args[cur_arg], "insert")) {
1655 curproxy->options |= PR_O_COOK_INS;
1656 }
1657 else if (!strcmp(args[cur_arg], "nocache")) {
1658 curproxy->options |= PR_O_COOK_NOC;
1659 }
1660 else if (!strcmp(args[cur_arg], "postonly")) {
1661 curproxy->options |= PR_O_COOK_POST;
1662 }
1663 else if (!strcmp(args[cur_arg], "prefix")) {
1664 curproxy->options |= PR_O_COOK_PFX;
1665 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001666 else if (!strcmp(args[cur_arg], "domain")) {
1667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1669 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001672 }
1673
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001674 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001676 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1677 " dots nor does not start with a dot."
1678 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001679 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001680 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001681 }
1682
1683 err = invalid_domainchar(args[cur_arg + 1]);
1684 if (err) {
1685 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1686 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001689 }
1690
Willy Tarreau68a897b2009-12-03 23:28:34 +01001691 if (!curproxy->cookie_domain) {
1692 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1693 } else {
1694 /* one domain was already specified, add another one by
1695 * building the string which will be returned along with
1696 * the cookie.
1697 */
1698 char *new_ptr;
1699 int new_len = strlen(curproxy->cookie_domain) +
1700 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1701 new_ptr = malloc(new_len);
1702 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1703 free(curproxy->cookie_domain);
1704 curproxy->cookie_domain = new_ptr;
1705 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001706 cur_arg++;
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 }
1714 cur_arg++;
1715 }
1716 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1717 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1718 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001719 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 }
1721
1722 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1723 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1724 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 }
1727 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001728 else if (!strcmp(args[0], "persist")) { /* persist */
1729 if (*(args[1]) == 0) {
1730 Alert("parsing [%s:%d] : missing persist method.\n",
1731 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001734 }
1735
1736 if (!strncmp(args[1], "rdp-cookie", 10)) {
1737 curproxy->options2 |= PR_O2_RDPC_PRST;
1738
Emeric Brunb982a3d2010-01-04 15:45:53 +01001739 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001740 const char *beg, *end;
1741
1742 beg = args[1] + 11;
1743 end = strchr(beg, ')');
1744
1745 if (!end || end == beg) {
1746 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001750 }
1751
1752 free(curproxy->rdp_cookie_name);
1753 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1754 curproxy->rdp_cookie_len = end-beg;
1755 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001756 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001757 free(curproxy->rdp_cookie_name);
1758 curproxy->rdp_cookie_name = strdup("msts");
1759 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1760 }
1761 else { /* syntax */
1762 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1763 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001766 }
1767 }
1768 else {
1769 Alert("parsing [%s:%d] : unknown persist method.\n",
1770 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001773 }
1774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001776 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001778 if (curproxy == &defproxy) {
1779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau977b8e42006-12-29 14:19:17 +01001784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001788 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 }
1793 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001794 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 curproxy->appsession_name = strdup(args[1]);
1796 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1797 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001798 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1799 if (err) {
1800 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1801 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001804 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001805 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001806
Willy Tarreau51041c72007-09-09 21:56:53 +02001807 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1808 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_ALERT | ERR_ABORT;
1810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001812
1813 cur_arg = 6;
1814 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001815 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1816 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001817 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001818 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001819 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001820 } else if (!strcmp(args[cur_arg], "prefix")) {
1821 curproxy->options2 |= PR_O2_AS_PFX;
1822 } else if (!strcmp(args[cur_arg], "mode")) {
1823 if (!*args[cur_arg + 1]) {
1824 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1825 file, linenum, args[0], args[cur_arg]);
1826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829
1830 cur_arg++;
1831 if (!strcmp(args[cur_arg], "query-string")) {
1832 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1833 curproxy->options2 |= PR_O2_AS_M_QS;
1834 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1836 curproxy->options2 |= PR_O2_AS_M_PP;
1837 } else {
1838 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001843 cur_arg++;
1844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 } /* Url App Session */
1846 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001851 if (curproxy == &defproxy) {
1852 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if (*(args[4]) == 0) {
1858 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001863 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->capture_name = strdup(args[2]);
1865 curproxy->capture_namelen = strlen(curproxy->capture_name);
1866 curproxy->capture_len = atol(args[4]);
1867 if (curproxy->capture_len >= CAPTURE_LEN) {
1868 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1869 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->capture_len = CAPTURE_LEN - 1;
1872 }
1873 curproxy->to_log |= LW_COOKIE;
1874 }
1875 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1876 struct cap_hdr *hdr;
1877
1878 if (curproxy == &defproxy) {
1879 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 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 }
1883
1884 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1885 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1886 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
1890
1891 hdr = calloc(sizeof(struct cap_hdr), 1);
1892 hdr->next = curproxy->req_cap;
1893 hdr->name = strdup(args[3]);
1894 hdr->namelen = strlen(args[3]);
1895 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001896 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 hdr->index = curproxy->nb_req_cap++;
1898 curproxy->req_cap = hdr;
1899 curproxy->to_log |= LW_REQHDR;
1900 }
1901 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1902 struct cap_hdr *hdr;
1903
1904 if (curproxy == &defproxy) {
1905 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 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909
1910 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1911 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1912 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
1916 hdr = calloc(sizeof(struct cap_hdr), 1);
1917 hdr->next = curproxy->rsp_cap;
1918 hdr->name = strdup(args[3]);
1919 hdr->namelen = strlen(args[3]);
1920 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001921 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 hdr->index = curproxy->nb_rsp_cap++;
1923 curproxy->rsp_cap = hdr;
1924 curproxy->to_log |= LW_RSPHDR;
1925 }
1926 else {
1927 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 if (*(args[1]) == 0) {
1938 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
1943 curproxy->conn_retries = atol(args[1]);
1944 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001945 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1946 struct req_acl_rule *req_acl;
1947
1948 if (curproxy == &defproxy) {
1949 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
1952 }
1953
1954
1955 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1956 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1957 file, linenum, args[0]);
1958 err_code |= ERR_WARN;
1959 }
1960
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001961 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001962
1963 if (!req_acl) {
1964 err_code |= ERR_ALERT | ERR_ABORT;
1965 goto out;
1966 }
1967
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001968 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001969 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1970 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001971 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001972 if (curproxy == &defproxy) {
1973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001976 }
1977
Willy Tarreauef6494c2010-01-28 17:12:36 +01001978 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001979 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1980 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001983 }
1984
Willy Tarreauef6494c2010-01-28 17:12:36 +01001985 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001986 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001990 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001991
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001992 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001993 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001994 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001995 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 struct redirect_rule *rule;
1997 int cur_arg;
1998 int type = REDIRECT_TYPE_NONE;
1999 int code = 302;
2000 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002001 char *cookie = NULL;
2002 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002003 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002004
Cyril Bonté99ed3272010-01-24 23:29:44 +01002005 if (curproxy == &defproxy) {
2006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002011 cur_arg = 1;
2012 while (*(args[cur_arg])) {
2013 if (!strcmp(args[cur_arg], "location")) {
2014 if (!*args[cur_arg + 1]) {
2015 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2016 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002019 }
2020
2021 type = REDIRECT_TYPE_LOCATION;
2022 cur_arg++;
2023 destination = args[cur_arg];
2024 }
2025 else if (!strcmp(args[cur_arg], "prefix")) {
2026 if (!*args[cur_arg + 1]) {
2027 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2028 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002031 }
2032
2033 type = REDIRECT_TYPE_PREFIX;
2034 cur_arg++;
2035 destination = args[cur_arg];
2036 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002037 else if (!strcmp(args[cur_arg], "set-cookie")) {
2038 if (!*args[cur_arg + 1]) {
2039 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2040 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002043 }
2044
2045 cur_arg++;
2046 cookie = args[cur_arg];
2047 cookie_set = 1;
2048 }
2049 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2050 if (!*args[cur_arg + 1]) {
2051 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2052 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002055 }
2056
2057 cur_arg++;
2058 cookie = args[cur_arg];
2059 cookie_set = 0;
2060 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002061 else if (!strcmp(args[cur_arg],"code")) {
2062 if (!*args[cur_arg + 1]) {
2063 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002067 }
2068 cur_arg++;
2069 code = atol(args[cur_arg]);
2070 if (code < 301 || code > 303) {
2071 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2072 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002075 }
2076 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002077 else if (!strcmp(args[cur_arg],"drop-query")) {
2078 flags |= REDIRECT_FLAG_DROP_QS;
2079 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002080 else if (!strcmp(args[cur_arg],"append-slash")) {
2081 flags |= REDIRECT_FLAG_APPEND_SLASH;
2082 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002083 else if (strcmp(args[cur_arg], "if") == 0 ||
2084 strcmp(args[cur_arg], "unless") == 0) {
2085 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2086 if (!cond) {
2087 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2088 file, linenum, args[0]);
2089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002092 break;
2093 }
2094 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002095 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 +02002096 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002099 }
2100 cur_arg++;
2101 }
2102
2103 if (type == REDIRECT_TYPE_NONE) {
2104 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002108 }
2109
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002110 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2111 rule->cond = cond;
2112 rule->rdr_str = strdup(destination);
2113 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002114 if (cookie) {
2115 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2116 * a clear consists in appending "; Max-Age=0" at the end.
2117 */
2118 rule->cookie_len = strlen(cookie);
2119 if (cookie_set)
2120 rule->cookie_str = strdup(cookie);
2121 else {
2122 rule->cookie_str = malloc(rule->cookie_len + 12);
2123 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2124 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2125 rule->cookie_len += 11;
2126 }
2127 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002128 rule->type = type;
2129 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002130 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002131 LIST_INIT(&rule->list);
2132 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002133 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002134 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002135 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002136 struct switching_rule *rule;
2137
Willy Tarreaub099aca2008-10-12 17:26:37 +02002138 if (curproxy == &defproxy) {
2139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002142 }
2143
Willy Tarreau55ea7572007-06-17 19:56:27 +02002144 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002146
2147 if (*(args[1]) == 0) {
2148 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002151 }
2152
Willy Tarreauef6494c2010-01-28 17:12:36 +01002153 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002154 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002158 }
2159
Willy Tarreauef6494c2010-01-28 17:12:36 +01002160 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002161 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002162 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002165 }
2166
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002167 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002168
Willy Tarreau55ea7572007-06-17 19:56:27 +02002169 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2170 rule->cond = cond;
2171 rule->be.name = strdup(args[1]);
2172 LIST_INIT(&rule->list);
2173 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2174 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002175 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002176 struct force_persist_rule *rule;
2177
2178 if (curproxy == &defproxy) {
2179 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
2183
2184 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2185 err_code |= ERR_WARN;
2186
Willy Tarreauef6494c2010-01-28 17:12:36 +01002187 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002188 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2189 file, linenum, args[0]);
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
Willy Tarreauef6494c2010-01-28 17:12:36 +01002194 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002195 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2196 file, linenum);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002201 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002202
2203 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2204 rule->cond = cond;
2205 LIST_INIT(&rule->list);
2206 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2207 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002208 else if (!strcmp(args[0], "stick-table")) {
2209 int myidx = 1;
2210
2211 curproxy->table.type = (unsigned int)-1;
2212 while (*args[myidx]) {
2213 const char *err;
2214
2215 if (strcmp(args[myidx], "size") == 0) {
2216 myidx++;
2217 if (!*(args[myidx])) {
2218 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2219 file, linenum, args[myidx-1]);
2220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
2222 }
2223 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2224 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2225 file, linenum, *err, args[myidx-1]);
2226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
2228 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002229 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002230 }
2231 else if (strcmp(args[myidx], "expire") == 0) {
2232 myidx++;
2233 if (!*(args[myidx])) {
2234 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2235 file, linenum, args[myidx-1]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2240 if (err) {
2241 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2242 file, linenum, *err, args[myidx-1]);
2243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
2245 }
2246 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002247 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002248 }
2249 else if (strcmp(args[myidx], "nopurge") == 0) {
2250 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002251 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002252 }
2253 else if (strcmp(args[myidx], "type") == 0) {
2254 myidx++;
2255 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2256 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2257 file, linenum, args[myidx]);
2258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
2260 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002261 /* myidx already points to next arg */
2262 }
2263 else {
2264 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2265 file, linenum, args[myidx]);
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002268 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002269 }
2270
2271 if (!curproxy->table.size) {
2272 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2273 file, linenum);
2274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
2276 }
2277
2278 if (curproxy->table.type == (unsigned int)-1) {
2279 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2280 file, linenum);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284 }
2285 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002286 struct sticking_rule *rule;
2287 struct pattern_expr *expr;
2288 int myidx = 0;
2289 const char *name = NULL;
2290 int flags;
2291
2292 if (curproxy == &defproxy) {
2293 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297
2298 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2299 err_code |= ERR_WARN;
2300 goto out;
2301 }
2302
2303 myidx++;
2304 if ((strcmp(args[myidx], "store") == 0) ||
2305 (strcmp(args[myidx], "store-request") == 0)) {
2306 myidx++;
2307 flags = STK_IS_STORE;
2308 }
2309 else if (strcmp(args[myidx], "store-response") == 0) {
2310 myidx++;
2311 flags = STK_IS_STORE | STK_ON_RSP;
2312 }
2313 else if (strcmp(args[myidx], "match") == 0) {
2314 myidx++;
2315 flags = STK_IS_MATCH;
2316 }
2317 else if (strcmp(args[myidx], "on") == 0) {
2318 myidx++;
2319 flags = STK_IS_MATCH | STK_IS_STORE;
2320 }
2321 else {
2322 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
2326
2327 if (*(args[myidx]) == 0) {
2328 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332
2333 expr = pattern_parse_expr(args, &myidx);
2334 if (!expr) {
2335 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339
2340 if (flags & STK_ON_RSP) {
2341 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2342 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2343 file, linenum, args[0], expr->fetch->kw);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 } else {
2348 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2349 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2350 file, linenum, args[0], expr->fetch->kw);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
2354 }
2355
2356 if (strcmp(args[myidx], "table") == 0) {
2357 myidx++;
2358 name = args[myidx++];
2359 }
2360
Willy Tarreauef6494c2010-01-28 17:12:36 +01002361 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2362 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002363 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2364 file, linenum, args[0]);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002368 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002369 else if (*(args[myidx])) {
2370 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2371 file, linenum, args[0], args[myidx]);
2372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
2374 }
2375
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002376 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2377
Emeric Brunb982a3d2010-01-04 15:45:53 +01002378 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2379 rule->cond = cond;
2380 rule->expr = expr;
2381 rule->flags = flags;
2382 rule->table.name = name ? strdup(name) : NULL;
2383 LIST_INIT(&rule->list);
2384 if (flags & STK_ON_RSP)
2385 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2386 else
2387 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002392
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2394 curproxy->uri_auth = NULL; /* we must detach from the default config */
2395
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002396 if (!*args[1]) {
2397 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 } else if (!strcmp(args[1], "uri")) {
2399 if (*(args[2]) == 0) {
2400 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2404 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_ABORT;
2406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 }
2408 } else if (!strcmp(args[1], "realm")) {
2409 if (*(args[2]) == 0) {
2410 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_ABORT;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002418 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002419 unsigned interval;
2420
2421 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2422 if (err) {
2423 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2424 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002427 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2428 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_ABORT;
2430 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002431 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002432 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2433 struct req_acl_rule *req_acl;
2434
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
2440
2441 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2442 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2443 err_code |= ERR_ALERT | ERR_ABORT;
2444 goto out;
2445 }
2446
2447 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2448 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2449 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2450 file, linenum, args[0]);
2451 err_code |= ERR_WARN;
2452 }
2453
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002454 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002455
2456 if (!req_acl) {
2457 err_code |= ERR_ALERT | ERR_ABORT;
2458 goto out;
2459 }
2460
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002461 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002462 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2463
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 } else if (!strcmp(args[1], "auth")) {
2465 if (*(args[2]) == 0) {
2466 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_ABORT;
2472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
2474 } else if (!strcmp(args[1], "scope")) {
2475 if (*(args[2]) == 0) {
2476 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2480 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_ABORT;
2482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 }
2484 } else if (!strcmp(args[1], "enable")) {
2485 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2486 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_ABORT;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002490 } else if (!strcmp(args[1], "hide-version")) {
2491 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2492 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_ABORT;
2494 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002495 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002496 } else if (!strcmp(args[1], "show-legends")) {
2497 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2498 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
2501 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002502 } else if (!strcmp(args[1], "show-node")) {
2503
2504 if (*args[2]) {
2505 int i;
2506 char c;
2507
2508 for (i=0; args[2][i]; i++) {
2509 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002510 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2511 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002512 break;
2513 }
2514
2515 if (!i || args[2][i]) {
2516 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2517 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2518 file, linenum, args[0], args[1]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522 }
2523
2524 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2525 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2526 err_code |= ERR_ALERT | ERR_ABORT;
2527 goto out;
2528 }
2529 } else if (!strcmp(args[1], "show-desc")) {
2530 char *desc = NULL;
2531
2532 if (*args[2]) {
2533 int i, len=0;
2534 char *d;
2535
2536 for(i=2; *args[i]; i++)
2537 len += strlen(args[i])+1;
2538
2539 desc = d = (char *)calloc(1, len);
2540
2541 d += sprintf(d, "%s", args[2]);
2542 for(i=3; *args[i]; i++)
2543 d += sprintf(d, " %s", args[i]);
2544 }
2545
2546 if (!*args[2] && !global.desc)
2547 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2548 file, linenum, args[1]);
2549 else {
2550 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2551 free(desc);
2552 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2553 err_code |= ERR_ALERT | ERR_ABORT;
2554 goto out;
2555 }
2556 free(desc);
2557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002559stats_error_parsing:
2560 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2561 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 }
2566 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002567 int optnum;
2568
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002569 if (*(args[1]) == '\0') {
2570 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002575
2576 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2577 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002578 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2579 err_code |= ERR_WARN;
2580 goto out;
2581 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002582
Willy Tarreau3842f002009-06-14 11:39:52 +02002583 curproxy->no_options &= ~cfg_opts[optnum].val;
2584 curproxy->options &= ~cfg_opts[optnum].val;
2585
2586 switch (kwm) {
2587 case KWM_STD:
2588 curproxy->options |= cfg_opts[optnum].val;
2589 break;
2590 case KWM_NO:
2591 curproxy->no_options |= cfg_opts[optnum].val;
2592 break;
2593 case KWM_DEF: /* already cleared */
2594 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002595 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002596
Willy Tarreau93893792009-07-23 13:19:11 +02002597 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002598 }
2599 }
2600
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002601 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2602 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002603 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2604 err_code |= ERR_WARN;
2605 goto out;
2606 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002607
Willy Tarreau3842f002009-06-14 11:39:52 +02002608 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2609 curproxy->options2 &= ~cfg_opts2[optnum].val;
2610
2611 switch (kwm) {
2612 case KWM_STD:
2613 curproxy->options2 |= cfg_opts2[optnum].val;
2614 break;
2615 case KWM_NO:
2616 curproxy->no_options2 |= cfg_opts2[optnum].val;
2617 break;
2618 case KWM_DEF: /* already cleared */
2619 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002620 }
Willy Tarreau93893792009-07-23 13:19:11 +02002621 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002622 }
2623 }
2624
Willy Tarreau3842f002009-06-14 11:39:52 +02002625 if (kwm != KWM_STD) {
2626 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002627 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002630 }
2631
Emeric Brun3a058f32009-06-30 18:26:00 +02002632 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002634 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002636 if (*(args[2]) != '\0') {
2637 if (!strcmp(args[2], "clf")) {
2638 curproxy->options2 |= PR_O2_CLFLOG;
2639 } else {
2640 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002643 }
2644 }
2645 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 else if (!strcmp(args[1], "tcplog"))
2647 /* generate a detailed TCP log */
2648 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else if (!strcmp(args[1], "tcpka")) {
2650 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002651 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002652 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002653
2654 if (curproxy->cap & PR_CAP_FE)
2655 curproxy->options |= PR_O_TCP_CLI_KA;
2656 if (curproxy->cap & PR_CAP_BE)
2657 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 }
2659 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002660 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_WARN;
2662
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002664 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002665 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002666 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002667 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002668 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002669 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 if (!*args[2]) { /* no argument */
2671 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2672 curproxy->check_len = strlen(DEF_CHECK_REQ);
2673 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002674 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 curproxy->check_req = (char *)malloc(reqlen);
2676 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002677 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002679 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 if (*args[4])
2681 reqlen += strlen(args[4]);
2682 else
2683 reqlen += strlen("HTTP/1.0");
2684
2685 curproxy->check_req = (char *)malloc(reqlen);
2686 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002687 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002689 }
2690 else if (!strcmp(args[1], "ssl-hello-chk")) {
2691 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002694
Willy Tarreaua534fea2008-08-03 12:19:50 +02002695 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002696 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002697 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002698 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002699 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002700 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
Willy Tarreau23677902007-05-08 23:50:35 +02002702 else if (!strcmp(args[1], "smtpchk")) {
2703 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002704 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002705 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002706 curproxy->options &= ~PR_O_HTTP_CHK;
2707 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002708 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002709 curproxy->options |= PR_O_SMTP_CHK;
2710
2711 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2712 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2713 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2714 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2715 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2716 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2717 curproxy->check_req = (char *)malloc(reqlen);
2718 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2719 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2720 } else {
2721 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2722 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2723 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2724 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2725 }
2726 }
2727 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002728 else if (!strcmp(args[1], "mysql-check")) {
2729 /* use MYSQL request to check servers' health */
2730 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002731 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002732 curproxy->options &= ~PR_O_HTTP_CHK;
2733 curproxy->options &= ~PR_O_SSL3_CHK;
2734 curproxy->options &= ~PR_O_SMTP_CHK;
2735 curproxy->options2 |= PR_O2_MYSQL_CHK;
2736 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002737 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002738 int cur_arg;
2739
2740 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2741 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002742 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002743
2744 curproxy->options |= PR_O_FWDFOR;
2745
2746 free(curproxy->fwdfor_hdr_name);
2747 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2748 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2749
2750 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2751 cur_arg = 2;
2752 while (*(args[cur_arg])) {
2753 if (!strcmp(args[cur_arg], "except")) {
2754 /* suboption except - needs additional argument for it */
2755 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2756 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2757 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002760 }
2761 /* flush useless bits */
2762 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002763 cur_arg += 2;
2764 } else if (!strcmp(args[cur_arg], "header")) {
2765 /* suboption header - needs additional argument for it */
2766 if (*(args[cur_arg+1]) == 0) {
2767 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2768 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002771 }
2772 free(curproxy->fwdfor_hdr_name);
2773 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2774 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2775 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002776 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002777 /* unknown suboption - catchall */
2778 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2779 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002782 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002783 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002784 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002785 else if (!strcmp(args[1], "originalto")) {
2786 int cur_arg;
2787
2788 /* insert x-original-to field, but not for the IP address listed as an except.
2789 * set default options (ie: bitfield, header name, etc)
2790 */
2791
2792 curproxy->options |= PR_O_ORGTO;
2793
2794 free(curproxy->orgto_hdr_name);
2795 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2796 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2797
2798 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2799 cur_arg = 2;
2800 while (*(args[cur_arg])) {
2801 if (!strcmp(args[cur_arg], "except")) {
2802 /* suboption except - needs additional argument for it */
2803 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2804 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2805 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002808 }
2809 /* flush useless bits */
2810 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2811 cur_arg += 2;
2812 } else if (!strcmp(args[cur_arg], "header")) {
2813 /* suboption header - needs additional argument for it */
2814 if (*(args[cur_arg+1]) == 0) {
2815 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2816 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002819 }
2820 free(curproxy->orgto_hdr_name);
2821 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2822 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2823 cur_arg += 2;
2824 } else {
2825 /* unknown suboption - catchall */
2826 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2827 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002830 }
2831 } /* end while loop */
2832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 else {
2834 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
Willy Tarreau93893792009-07-23 13:19:11 +02002838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002840 else if (!strcmp(args[0], "default_backend")) {
2841 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002843
2844 if (*(args[1]) == 0) {
2845 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002848 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002849 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002850 curproxy->defbe.name = strdup(args[1]);
2851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002855
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002856 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2857 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 /* enable reconnections to dispatch */
2860 curproxy->options |= PR_O_REDISP;
2861 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002862 else if (!strcmp(args[0], "http-check")) {
2863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002865
2866 if (strcmp(args[1], "disable-on-404") == 0) {
2867 /* enable a graceful server shutdown on an HTTP 404 response */
2868 curproxy->options |= PR_O_DISABLE404;
2869 }
Willy Tarreauef781042010-01-27 11:53:01 +01002870 else if (strcmp(args[1], "send-state") == 0) {
2871 /* enable emission of the apparent state of a server in HTTP checks */
2872 curproxy->options2 |= PR_O2_CHK_SNDST;
2873 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002874 else {
2875 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002878 }
2879 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002880 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002881 if (curproxy == &defproxy) {
2882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002885 }
2886
Willy Tarreaub80c2302007-11-30 20:51:32 +01002887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002889
2890 if (strcmp(args[1], "fail") == 0) {
2891 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002892 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002893 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2894 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002897 }
2898
Willy Tarreauef6494c2010-01-28 17:12:36 +01002899 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002900 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2901 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002904 }
2905 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2906 }
2907 else {
2908 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002911 }
2912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913#ifdef TPROXY
2914 else if (!strcmp(args[0], "transparent")) {
2915 /* enable transparent proxy connections */
2916 curproxy->options |= PR_O_TRANSP;
2917 }
2918#endif
2919 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002922
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 if (*(args[1]) == 0) {
2924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002927 }
2928 curproxy->maxconn = atol(args[1]);
2929 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002930 else if (!strcmp(args[0], "backlog")) { /* backlog */
2931 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002933
2934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002938 }
2939 curproxy->backlog = atol(args[1]);
2940 }
Willy Tarreau86034312006-12-29 00:10:33 +01002941 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002942 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944
Willy Tarreau86034312006-12-29 00:10:33 +01002945 if (*(args[1]) == 0) {
2946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002949 }
2950 curproxy->fullconn = atol(args[1]);
2951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2953 if (*(args[1]) == 0) {
2954 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002958 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2959 if (err) {
2960 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2961 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002964 }
2965 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002968 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 if (curproxy == &defproxy) {
2970 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 if (strchr(args[1], ':') == NULL) {
2978 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002982 sk = str2sa(args[1]);
2983 if (!sk) {
2984 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 }
2990 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002993
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002994 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002995 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2996 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003001 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3002 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3003 err_code |= ERR_WARN;
3004
3005 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3006 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3007 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3008 }
3009 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3010 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3011 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3012 }
3013 else {
3014 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003019 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003021 char *rport, *raddr;
3022 short realport = 0;
3023 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003025 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003030 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032
3033 if (!*args[2]) {
3034 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003039
3040 err = invalid_char(args[1]);
3041 if (err) {
3042 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3043 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003046 }
3047
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003048 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003049 struct sockaddr_in *sk;
3050
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003051 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3052 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3053 err_code |= ERR_ALERT | ERR_ABORT;
3054 goto out;
3055 }
3056
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003057 /* the servers are linked backwards first */
3058 newsrv->next = curproxy->srv;
3059 curproxy->srv = newsrv;
3060 newsrv->proxy = curproxy;
3061 newsrv->conf.file = file;
3062 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003064 LIST_INIT(&newsrv->pendconns);
3065 do_check = 0;
3066 newsrv->state = SRV_RUNNING; /* early server setup */
3067 newsrv->last_change = now.tv_sec;
3068 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003070 /* several ways to check the port component :
3071 * - IP => port=+0, relative
3072 * - IP: => port=+0, relative
3073 * - IP:N => port=N, absolute
3074 * - IP:+N => port=+N, relative
3075 * - IP:-N => port=-N, relative
3076 */
3077 raddr = strdup(args[2]);
3078 rport = strchr(raddr, ':');
3079 if (rport) {
3080 *rport++ = 0;
3081 realport = atol(rport);
3082 if (!isdigit((unsigned char)*rport))
3083 newsrv->state |= SRV_MAPPORTS;
3084 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003086
Willy Tarreaud5191e72010-02-09 20:50:45 +01003087 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003088 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003089 if (!sk) {
3090 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094 newsrv->addr = *sk;
3095 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003096
3097 newsrv->check_port = curproxy->defsrv.check_port;
3098 newsrv->inter = curproxy->defsrv.inter;
3099 newsrv->fastinter = curproxy->defsrv.fastinter;
3100 newsrv->downinter = curproxy->defsrv.downinter;
3101 newsrv->rise = curproxy->defsrv.rise;
3102 newsrv->fall = curproxy->defsrv.fall;
3103 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3104 newsrv->minconn = curproxy->defsrv.minconn;
3105 newsrv->maxconn = curproxy->defsrv.maxconn;
3106 newsrv->slowstart = curproxy->defsrv.slowstart;
3107 newsrv->onerror = curproxy->defsrv.onerror;
3108 newsrv->consecutive_errors_limit
3109 = curproxy->defsrv.consecutive_errors_limit;
3110 newsrv->uweight = newsrv->iweight
3111 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003113 newsrv->curfd = -1; /* no health-check in progress */
3114 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003116 cur_arg = 3;
3117 } else {
3118 newsrv = &curproxy->defsrv;
3119 cur_arg = 1;
3120 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003121
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003123 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003124 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003125
3126 if (!*args[cur_arg + 1]) {
3127 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3128 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003131 }
3132
3133 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003134 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003135
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003136 if (newsrv->puid <= 0) {
3137 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003138 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003141 }
3142
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003143 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3144 if (node) {
3145 struct server *target = container_of(node, struct server, conf.id);
3146 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3147 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003152 cur_arg += 2;
3153 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003154 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 newsrv->cookie = strdup(args[cur_arg + 1]);
3156 newsrv->cklen = strlen(args[cur_arg + 1]);
3157 cur_arg += 2;
3158 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003159 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003160 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3161 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3162 cur_arg += 2;
3163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003165 if (!*args[cur_arg + 1]) {
3166 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3167 file, linenum, args[cur_arg]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003173 if (newsrv->rise <= 0) {
3174 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3175 file, linenum, args[cur_arg]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
3179
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 newsrv->health = newsrv->rise;
3181 cur_arg += 2;
3182 }
3183 else if (!strcmp(args[cur_arg], "fall")) {
3184 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003185
3186 if (!*args[cur_arg + 1]) {
3187 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3188 file, linenum, args[cur_arg]);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
3191 }
3192
3193 if (newsrv->fall <= 0) {
3194 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3195 file, linenum, args[cur_arg]);
3196 err_code |= ERR_ALERT | ERR_FATAL;
3197 goto out;
3198 }
3199
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 cur_arg += 2;
3201 }
3202 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003203 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3204 if (err) {
3205 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3206 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003209 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003210 if (val <= 0) {
3211 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3212 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003215 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003216 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 cur_arg += 2;
3218 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003219 else if (!strcmp(args[cur_arg], "fastinter")) {
3220 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3221 if (err) {
3222 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3223 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003226 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003227 if (val <= 0) {
3228 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3229 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003232 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003233 newsrv->fastinter = val;
3234 cur_arg += 2;
3235 }
3236 else if (!strcmp(args[cur_arg], "downinter")) {
3237 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3238 if (err) {
3239 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3240 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003243 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003244 if (val <= 0) {
3245 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3246 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003249 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003250 newsrv->downinter = val;
3251 cur_arg += 2;
3252 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003253 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003254 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3255 if (!sk) {
3256 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003261 cur_arg += 2;
3262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 else if (!strcmp(args[cur_arg], "port")) {
3264 newsrv->check_port = atol(args[cur_arg + 1]);
3265 cur_arg += 2;
3266 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003267 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 newsrv->state |= SRV_BACKUP;
3269 cur_arg ++;
3270 }
3271 else if (!strcmp(args[cur_arg], "weight")) {
3272 int w;
3273 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003274 if (w < 0 || w > 256) {
3275 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003280 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 cur_arg += 2;
3282 }
3283 else if (!strcmp(args[cur_arg], "minconn")) {
3284 newsrv->minconn = atol(args[cur_arg + 1]);
3285 cur_arg += 2;
3286 }
3287 else if (!strcmp(args[cur_arg], "maxconn")) {
3288 newsrv->maxconn = atol(args[cur_arg + 1]);
3289 cur_arg += 2;
3290 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003291 else if (!strcmp(args[cur_arg], "maxqueue")) {
3292 newsrv->maxqueue = atol(args[cur_arg + 1]);
3293 cur_arg += 2;
3294 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003295 else if (!strcmp(args[cur_arg], "slowstart")) {
3296 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003297 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003298 if (err) {
3299 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3300 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003303 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003304 if (val <= 0) {
3305 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3306 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003309 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003310 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003311 cur_arg += 2;
3312 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003313 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003314
3315 if (!*args[cur_arg + 1]) {
3316 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003320 }
3321
3322 newsrv->trackit = strdup(args[cur_arg + 1]);
3323
3324 cur_arg += 2;
3325 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003326 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 global.maxsock++;
3328 do_check = 1;
3329 cur_arg += 1;
3330 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003331 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003332 if (!strcmp(args[cur_arg + 1], "none"))
3333 newsrv->observe = HANA_OBS_NONE;
3334 else if (!strcmp(args[cur_arg + 1], "layer4"))
3335 newsrv->observe = HANA_OBS_LAYER4;
3336 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3337 if (curproxy->mode != PR_MODE_HTTP) {
3338 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3339 file, linenum, args[cur_arg + 1]);
3340 err_code |= ERR_ALERT;
3341 }
3342 newsrv->observe = HANA_OBS_LAYER7;
3343 }
3344 else {
3345 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3346 "'l4events', 'http-responses' but get '%s'\n",
3347 file, linenum, args[cur_arg], args[cur_arg + 1]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351
3352 cur_arg += 2;
3353 }
3354 else if (!strcmp(args[cur_arg], "on-error")) {
3355 if (!strcmp(args[cur_arg + 1], "fastinter"))
3356 newsrv->onerror = HANA_ONERR_FASTINTER;
3357 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3358 newsrv->onerror = HANA_ONERR_FAILCHK;
3359 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3360 newsrv->onerror = HANA_ONERR_SUDDTH;
3361 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3362 newsrv->onerror = HANA_ONERR_MARKDWN;
3363 else {
3364 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3365 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3366 file, linenum, args[cur_arg], args[cur_arg + 1]);
3367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
3369 }
3370
3371 cur_arg += 2;
3372 }
3373 else if (!strcmp(args[cur_arg], "error-limit")) {
3374 if (!*args[cur_arg + 1]) {
3375 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3376 file, linenum, args[cur_arg]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
3381 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3382
3383 if (newsrv->consecutive_errors_limit <= 0) {
3384 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3385 file, linenum, args[cur_arg]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003390 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003391 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003392 struct sockaddr_in *sk;
3393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003395#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003396 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003397 file, linenum, "source", "usesrc");
3398#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003399 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003401#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 }
3405 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003406 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3407 if (!sk) {
3408 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003413
3414 if (port_low != port_high) {
3415 int i;
3416 if (port_low <= 0 || port_low > 65535 ||
3417 port_high <= 0 || port_high > 65535 ||
3418 port_low > port_high) {
3419 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3420 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003423 }
3424 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3425 for (i = 0; i < newsrv->sport_range->size; i++)
3426 newsrv->sport_range->ports[i] = port_low + i;
3427 }
3428
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003430 while (*(args[cur_arg])) {
3431 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003432#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3433#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003434 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3435 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3436 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003439 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003440#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003441 if (!*args[cur_arg + 1]) {
3442 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3443 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003446 }
3447 if (!strcmp(args[cur_arg + 1], "client")) {
3448 newsrv->state |= SRV_TPROXY_CLI;
3449 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3450 newsrv->state |= SRV_TPROXY_CIP;
3451 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003452 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3453 if (!sk) {
3454 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003459 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003460 }
3461 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003462#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003463 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003464#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003465 cur_arg += 2;
3466 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003467#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003468 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003469 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003472#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3473 } /* "usesrc" */
3474
3475 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3476#ifdef SO_BINDTODEVICE
3477 if (!*args[cur_arg + 1]) {
3478 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3479 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003482 }
3483 if (newsrv->iface_name)
3484 free(newsrv->iface_name);
3485
3486 newsrv->iface_name = strdup(args[cur_arg + 1]);
3487 newsrv->iface_len = strlen(newsrv->iface_name);
3488 global.last_checks |= LSTCHK_NETADM;
3489#else
3490 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3491 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003494#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003495 cur_arg += 2;
3496 continue;
3497 }
3498 /* this keyword in not an option of "source" */
3499 break;
3500 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003502 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003503 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3504 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003509 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003510 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 +01003511 file, linenum, newsrv->id);
3512 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003513 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 +01003514 file, linenum);
3515
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 }
3520
3521 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003522 if (newsrv->trackit) {
3523 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3524 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003527 }
3528
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003529 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3530 newsrv->check_port = newsrv->check_addr.sin_port;
3531
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3533 newsrv->check_port = realport; /* by default */
3534 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003535 /* not yet valid, because no port was set on
3536 * the server either. We'll check if we have
3537 * a known port on the first listener.
3538 */
3539 struct listener *l;
3540 l = curproxy->listen;
3541 if (l) {
3542 int port;
3543 port = (l->addr.ss_family == AF_INET6)
3544 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3545 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3546 newsrv->check_port = port;
3547 }
3548 }
3549 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003550 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3551 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003555
3556 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 newsrv->state |= SRV_CHECKED;
3558 }
3559
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003560 if (!defsrv) {
3561 if (newsrv->state & SRV_BACKUP)
3562 curproxy->srv_bck++;
3563 else
3564 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003565
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003566 newsrv->prev_state = newsrv->state;
3567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568 }
3569 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003570 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 int facility;
3572
3573 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3574 curproxy->logfac1 = global.logfac1;
3575 curproxy->logsrv1 = global.logsrv1;
3576 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003577 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 curproxy->logfac2 = global.logfac2;
3579 curproxy->logsrv2 = global.logsrv2;
3580 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003581 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003584 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585
3586 facility = get_log_facility(args[2]);
3587 if (facility < 0) {
3588 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3589 exit(1);
3590 }
3591
3592 level = 7; /* max syslog level = debug */
3593 if (*(args[3])) {
3594 level = get_log_level(args[3]);
3595 if (level < 0) {
3596 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3597 exit(1);
3598 }
3599 }
3600
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003601 minlvl = 0; /* limit syslog level to this level (emerg) */
3602 if (*(args[4])) {
3603 minlvl = get_log_level(args[4]);
3604 if (level < 0) {
3605 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3606 exit(1);
3607 }
3608 }
3609
Robert Tsai81ae1952007-12-05 10:47:29 +01003610 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003611 struct sockaddr_un *sk = str2sun(args[1]);
3612 if (!sk) {
3613 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3614 args[1], (int)sizeof(sk->sun_path) - 1);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
3618 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003619 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003620 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003621 struct sockaddr_in *sk = str2sa(args[1]);
3622 if (!sk) {
3623 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003628 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003629 if (!logsrv.u.in.sin_port) {
3630 logsrv.u.in.sin_port =
3631 htons(SYSLOG_PORT);
3632 }
3633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634
3635 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003636 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 curproxy->logfac1 = facility;
3638 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003639 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
3641 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003642 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 curproxy->logfac2 = facility;
3644 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003645 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
3647 else {
3648 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652 }
3653 else {
3654 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
3659 }
3660 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003661 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003662 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003663
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003666
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003668 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3669 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003673
3674 /* we must first clear any optional default setting */
3675 curproxy->options &= ~PR_O_TPXY_MASK;
3676 free(curproxy->iface_name);
3677 curproxy->iface_name = NULL;
3678 curproxy->iface_len = 0;
3679
Willy Tarreaud5191e72010-02-09 20:50:45 +01003680 sk = str2sa(args[1]);
3681 if (!sk) {
3682 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
3685 }
3686 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003688
3689 cur_arg = 2;
3690 while (*(args[cur_arg])) {
3691 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003692#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3693#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003694 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3695 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3696 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003699 }
3700#endif
3701 if (!*args[cur_arg + 1]) {
3702 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3703 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003706 }
3707
3708 if (!strcmp(args[cur_arg + 1], "client")) {
3709 curproxy->options |= PR_O_TPXY_CLI;
3710 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3711 curproxy->options |= PR_O_TPXY_CIP;
3712 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003713 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3714 if (!sk) {
3715 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
3718 }
3719 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003720 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003721 }
3722 global.last_checks |= LSTCHK_NETADM;
3723#if !defined(CONFIG_HAP_LINUX_TPROXY)
3724 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003725#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003726#else /* no TPROXY support */
3727 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003728 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003731#endif
3732 cur_arg += 2;
3733 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003734 }
3735
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003736 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3737#ifdef SO_BINDTODEVICE
3738 if (!*args[cur_arg + 1]) {
3739 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003743 }
3744 if (curproxy->iface_name)
3745 free(curproxy->iface_name);
3746
3747 curproxy->iface_name = strdup(args[cur_arg + 1]);
3748 curproxy->iface_len = strlen(curproxy->iface_name);
3749 global.last_checks |= LSTCHK_NETADM;
3750#else
3751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003755#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003756 cur_arg += 2;
3757 continue;
3758 }
3759 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3760 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003765 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3766 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3767 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003772 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3774 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 Tarreauade5ec42010-01-28 19:33:49 +01003778
3779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3780 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003781 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
3785 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3787 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
3792 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3794 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 }
3799 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3801 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003802 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 }
3806 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3808 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003809 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003813 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3815 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003816 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003818 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003819 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003820 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3822 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003823 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003825 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003826 }
3827 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3829 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003830 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003832 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003835 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3837 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003841
3842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3843 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003844 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 }
3848 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3850 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 }
3855 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3857 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003858 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 }
3862 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003863 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3864 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003865 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003866 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
3869 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003870 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3871 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003872 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003873 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003876 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003877 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3878 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003879 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003880 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003881 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003884 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003885
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 if (curproxy == &defproxy) {
3887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 if (*(args[1]) == 0) {
3895 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003899
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003900 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3901 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3902 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3903 file, linenum, args[0]);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3908 }
3909 else if (*args[2]) {
3910 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3911 file, linenum, args[0], args[2]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003916 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003917 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003918 wl->s = strdup(args[1]);
3919 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003920 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
3922 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003923 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003929
Willy Tarreauade5ec42010-01-28 19:33:49 +01003930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3931 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
3936 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3938 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003939 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
3943 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3945 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
3950 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003951 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 }
3957
Willy Tarreauade5ec42010-01-28 19:33:49 +01003958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3959 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003960 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 }
3964 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3966 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
3971 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3973 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
3978 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003979 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003980
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 if (curproxy == &defproxy) {
3982 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003986 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 if (*(args[1]) == 0) {
3990 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 }
3994
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003995 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3996 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3997 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3998 file, linenum, args[0]);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002 err_code |= warnif_cond_requires_req(cond, file, linenum);
4003 }
4004 else if (*args[2]) {
4005 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4006 file, linenum, args[0], args[2]);
4007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004011 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004012 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004013 wl->s = strdup(args[1]);
4014 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 }
4016 else if (!strcmp(args[0], "errorloc") ||
4017 !strcmp(args[0], "errorloc302") ||
4018 !strcmp(args[0], "errorloc303")) { /* error location */
4019 int errnum, errlen;
4020 char *err;
4021
Willy Tarreau977b8e42006-12-29 14:19:17 +01004022 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004024
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004026 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 }
4030
4031 errnum = atol(args[1]);
4032 if (!strcmp(args[0], "errorloc303")) {
4033 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4034 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4035 } else {
4036 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4037 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4038 }
4039
Willy Tarreau0f772532006-12-23 20:51:41 +01004040 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4041 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004042 chunk_destroy(&curproxy->errmsg[rc]);
4043 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004044 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004047
4048 if (rc >= HTTP_ERR_SIZE) {
4049 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4050 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 free(err);
4052 }
4053 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004054 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4055 int errnum, errlen, fd;
4056 char *err;
4057 struct stat stat;
4058
4059 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004061
4062 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004063 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004066 }
4067
4068 fd = open(args[2], O_RDONLY);
4069 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4070 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4071 file, linenum, args[2], args[1]);
4072 if (fd >= 0)
4073 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004076 }
4077
Willy Tarreau27a674e2009-08-17 07:23:33 +02004078 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004079 errlen = stat.st_size;
4080 } else {
4081 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004082 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004084 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004085 }
4086
4087 err = malloc(errlen); /* malloc() must succeed during parsing */
4088 errnum = read(fd, err, errlen);
4089 if (errnum != errlen) {
4090 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4091 file, linenum, args[2], args[1]);
4092 close(fd);
4093 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004096 }
4097 close(fd);
4098
4099 errnum = atol(args[1]);
4100 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4101 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004102 chunk_destroy(&curproxy->errmsg[rc]);
4103 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004104 break;
4105 }
4106 }
4107
4108 if (rc >= HTTP_ERR_SIZE) {
4109 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4110 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004112 free(err);
4113 }
4114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004116 struct cfg_kw_list *kwl;
4117 int index;
4118
4119 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4120 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4121 if (kwl->kw[index].section != CFG_LISTEN)
4122 continue;
4123 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4124 /* prepare error message just in case */
4125 snprintf(trash, sizeof(trash),
4126 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004127 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4128 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004129 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004132 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004133 else if (rc > 0) {
4134 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004135 err_code |= ERR_WARN;
4136 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004137 }
Willy Tarreau93893792009-07-23 13:19:11 +02004138 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004139 }
4140 }
4141 }
4142
Willy Tarreau6daf3432008-01-22 16:44:08 +01004143 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 }
Willy Tarreau93893792009-07-23 13:19:11 +02004147 out:
4148 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149}
4150
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004151int
4152cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4153{
4154
4155 int err_code = 0;
4156 const char *err;
4157
4158 if (!strcmp(args[0], "userlist")) { /* new userlist */
4159 struct userlist *newul;
4160
4161 if (!*args[1]) {
4162 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4163 file, linenum, args[0]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167
4168 err = invalid_char(args[1]);
4169 if (err) {
4170 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4171 file, linenum, *err, args[0], args[1]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175
4176 for (newul = userlist; newul; newul = newul->next)
4177 if (!strcmp(newul->name, args[1])) {
4178 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4179 file, linenum, args[1]);
4180 err_code |= ERR_WARN;
4181 goto out;
4182 }
4183
4184 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4185 if (!newul) {
4186 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4187 err_code |= ERR_ALERT | ERR_ABORT;
4188 goto out;
4189 }
4190
4191 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4192 newul->name = strdup(args[1]);
4193
4194 if (!newul->groupusers | !newul->name) {
4195 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4196 err_code |= ERR_ALERT | ERR_ABORT;
4197 goto out;
4198 }
4199
4200 newul->next = userlist;
4201 userlist = newul;
4202
4203 } else if (!strcmp(args[0], "group")) { /* new group */
4204 int cur_arg, i;
4205 const char *err;
4206
4207 if (!*args[1]) {
4208 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4209 file, linenum, args[0]);
4210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
4212 }
4213
4214 err = invalid_char(args[1]);
4215 if (err) {
4216 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4217 file, linenum, *err, args[0], args[1]);
4218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
4220 }
4221
4222 for(i = 0; i < userlist->grpcnt; i++)
4223 if (!strcmp(userlist->groups[i], args[1])) {
4224 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4225 file, linenum, args[1], userlist->name);
4226 err_code |= ERR_ALERT;
4227 goto out;
4228 }
4229
4230 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4231 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4232 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235 }
4236
4237 cur_arg = 2;
4238
4239 while (*args[cur_arg]) {
4240 if (!strcmp(args[cur_arg], "users")) {
4241 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4242 cur_arg += 2;
4243 continue;
4244 } else {
4245 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4246 file, linenum, args[0]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250 }
4251
4252 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4253 } else if (!strcmp(args[0], "user")) { /* new user */
4254 struct auth_users *newuser;
4255 int cur_arg;
4256
4257 if (!*args[1]) {
4258 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4259 file, linenum, args[0]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 for (newuser = userlist->users; newuser; newuser = newuser->next)
4265 if (!strcmp(newuser->user, args[1])) {
4266 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4267 file, linenum, args[1], userlist->name);
4268 err_code |= ERR_ALERT;
4269 goto out;
4270 }
4271
4272 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4273 if (!newuser) {
4274 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
4277 }
4278
4279 newuser->user = strdup(args[1]);
4280
4281 newuser->next = userlist->users;
4282 userlist->users = newuser;
4283
4284 cur_arg = 2;
4285
4286 while (*args[cur_arg]) {
4287 if (!strcmp(args[cur_arg], "password")) {
4288#ifndef CONFIG_HAP_CRYPT
4289 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4290 file, linenum);
4291 err_code |= ERR_ALERT;
4292#endif
4293 newuser->pass = strdup(args[cur_arg + 1]);
4294 cur_arg += 2;
4295 continue;
4296 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4297 newuser->pass = strdup(args[cur_arg + 1]);
4298 newuser->flags |= AU_O_INSECURE;
4299 cur_arg += 2;
4300 continue;
4301 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004302 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004303 cur_arg += 2;
4304 continue;
4305 } else {
4306 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4307 file, linenum, args[0]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 }
4312 } else {
4313 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4314 err_code |= ERR_ALERT | ERR_FATAL;
4315 }
4316
4317out:
4318 return err_code;
4319}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320
4321/*
4322 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004323 * Returns the error code, 0 if OK, or any combination of :
4324 * - ERR_ABORT: must abort ASAP
4325 * - ERR_FATAL: we can continue parsing but not start the service
4326 * - ERR_WARN: a warning has been emitted
4327 * - ERR_ALERT: an alert has been emitted
4328 * Only the two first ones can stop processing, the two others are just
4329 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004331int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004333 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 FILE *f;
4335 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004337 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 if ((f=fopen(file,"r")) == NULL)
4340 return -1;
4341
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004342 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004343 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004344 char *end;
4345 char *args[MAX_LINE_ARGS + 1];
4346 char *line = thisline;
4347
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348 linenum++;
4349
4350 end = line + strlen(line);
4351
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004352 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4353 /* Check if we reached the limit and the last char is not \n.
4354 * Watch out for the last line without the terminating '\n'!
4355 */
4356 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004357 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004359 }
4360
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004362 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 line++;
4364
4365 arg = 0;
4366 args[arg] = line;
4367
4368 while (*line && arg < MAX_LINE_ARGS) {
4369 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4370 * C equivalent value. Other combinations left unchanged (eg: \1).
4371 */
4372 if (*line == '\\') {
4373 int skip = 0;
4374 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4375 *line = line[1];
4376 skip = 1;
4377 }
4378 else if (line[1] == 'r') {
4379 *line = '\r';
4380 skip = 1;
4381 }
4382 else if (line[1] == 'n') {
4383 *line = '\n';
4384 skip = 1;
4385 }
4386 else if (line[1] == 't') {
4387 *line = '\t';
4388 skip = 1;
4389 }
4390 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004391 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 unsigned char hex1, hex2;
4393 hex1 = toupper(line[2]) - '0';
4394 hex2 = toupper(line[3]) - '0';
4395 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4396 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4397 *line = (hex1<<4) + hex2;
4398 skip = 3;
4399 }
4400 else {
4401 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
4404 }
4405 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004406 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 end -= skip;
4408 }
4409 line++;
4410 }
4411 else if (*line == '#' || *line == '\n' || *line == '\r') {
4412 /* end of string, end of loop */
4413 *line = 0;
4414 break;
4415 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004416 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004418 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004419 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 line++;
4421 args[++arg] = line;
4422 }
4423 else {
4424 line++;
4425 }
4426 }
4427
4428 /* empty line */
4429 if (!**args)
4430 continue;
4431
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004432 if (*line) {
4433 /* we had to stop due to too many args.
4434 * Let's terminate the string, print the offending part then cut the
4435 * last arg.
4436 */
4437 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4438 line++;
4439 *line = '\0';
4440
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004441 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004442 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 args[arg] = line;
4445 }
4446
Willy Tarreau540abe42007-05-02 20:50:16 +02004447 /* zero out remaining args and ensure that at least one entry
4448 * is zeroed out.
4449 */
4450 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004451 args[arg] = line;
4452 }
4453
Willy Tarreau3842f002009-06-14 11:39:52 +02004454 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004455 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004456 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004457 for (arg=0; *args[arg+1]; arg++)
4458 args[arg] = args[arg+1]; // shift args after inversion
4459 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004460 else if (!strcmp(args[0], "default")) {
4461 kwm = KWM_DEF;
4462 for (arg=0; *args[arg+1]; arg++)
4463 args[arg] = args[arg+1]; // shift args after inversion
4464 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004465
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4467 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004469 }
4470
Willy Tarreau977b8e42006-12-29 14:19:17 +01004471 if (!strcmp(args[0], "listen") ||
4472 !strcmp(args[0], "frontend") ||
4473 !strcmp(args[0], "backend") ||
4474 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004475 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004477 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004478 cursection = strdup(args[0]);
4479 }
4480 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004482 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004483 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004484 } else if (!strcmp(args[0], "userlist")) {
4485 confsect = CFG_USERLIST;
4486 free(cursection);
4487 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 /* else it's a section keyword */
4490
4491 switch (confsect) {
4492 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 break;
4495 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004496 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004498 case CFG_USERLIST:
4499 err_code |= cfg_parse_users(file, linenum, args, kwm);
4500 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004502 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004505
4506 if (err_code & ERR_ABORT)
4507 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004509 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004510 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004512 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004513}
4514
Willy Tarreaubb925012009-07-23 13:36:36 +02004515/*
4516 * Returns the error code, 0 if OK, or any combination of :
4517 * - ERR_ABORT: must abort ASAP
4518 * - ERR_FATAL: we can continue parsing but not start the service
4519 * - ERR_WARN: a warning has been emitted
4520 * - ERR_ALERT: an alert has been emitted
4521 * Only the two first ones can stop processing, the two others are just
4522 * indicators.
4523 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004524int check_config_validity()
4525{
4526 int cfgerr = 0;
4527 struct proxy *curproxy = NULL;
4528 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004529 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004530 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004531 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532
4533 /*
4534 * Now, check for the integrity of all that we have collected.
4535 */
4536
4537 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004538 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004540 /* first, we will invert the proxy list order */
4541 curproxy = NULL;
4542 while (proxy) {
4543 struct proxy *next;
4544
4545 next = proxy->next;
4546 proxy->next = curproxy;
4547 curproxy = proxy;
4548 if (!next)
4549 break;
4550 proxy = next;
4551 }
4552
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004554 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 }
4558
4559 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004560 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004561 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004562 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004563 unsigned int next_id;
4564
4565 if (!curproxy->uuid) {
4566 /* proxy ID not set, use automatic numbering with first
4567 * spare entry starting with next_pxid.
4568 */
4569 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4570 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4571 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004572 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004573 next_pxid++;
4574
Willy Tarreau55ea7572007-06-17 19:56:27 +02004575
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004577 /* ensure we don't keep listeners uselessly bound */
4578 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 curproxy = curproxy->next;
4580 continue;
4581 }
4582
Willy Tarreauff01a212009-03-15 13:46:16 +01004583 switch (curproxy->mode) {
4584 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004585 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004586 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004587 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004589 cfgerr++;
4590 }
4591
4592 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004593 Warning("config : servers will be ignored for %s '%s'.\n",
4594 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004595 break;
4596
4597 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004598 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004599 break;
4600
4601 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004602 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004603 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004604 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4605 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004606 cfgerr++;
4607 }
4608 break;
4609 }
4610
4611 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004612 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 cfgerr++;
4615 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004616
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004617 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004618 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004619 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004620 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4621 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004622 cfgerr++;
4623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004625 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004626 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4627 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004628 cfgerr++;
4629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004631 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004632 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4633 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004634 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004635 }
4636 }
4637 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4638 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4639 /* If no LB algo is set in a backend, and we're not in
4640 * transparent mode, dispatch mode nor proxy mode, we
4641 * want to use balance roundrobin by default.
4642 */
4643 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4644 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 }
4646 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004647
Willy Tarreau82936582007-11-30 15:20:09 +01004648 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4649 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004650 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4651 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004652 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004653 }
4654
Willy Tarreauef781042010-01-27 11:53:01 +01004655 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4656 curproxy->options &= ~PR_O2_CHK_SNDST;
4657 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4658 "send-state", proxy_type_str(curproxy), curproxy->id);
4659 err_code |= ERR_WARN;
4660 }
4661
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004662 /* if a default backend was specified, let's find it */
4663 if (curproxy->defbe.name) {
4664 struct proxy *target;
4665
Alex Williams96532db2009-11-01 21:27:13 -05004666 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004667 if (!target) {
4668 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4669 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004670 cfgerr++;
4671 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004672 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4673 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004674 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004675 } else {
4676 free(curproxy->defbe.name);
4677 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004678 /* we force the backend to be present on at least all of
4679 * the frontend's processes.
4680 */
4681 target->bind_proc = curproxy->bind_proc ?
4682 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
4684 }
4685
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004686 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004687 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4688 /* map jump target for ACT_SETBE in req_rep chain */
4689 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004690 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004691 struct proxy *target;
4692
Willy Tarreaua496b602006-12-17 23:15:24 +01004693 if (exp->action != ACT_SETBE)
4694 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004695
Alex Williams96532db2009-11-01 21:27:13 -05004696 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004697 if (!target) {
4698 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4699 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004700 cfgerr++;
4701 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004702 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4703 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004704 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004705 } else {
4706 free((void *)exp->replace);
4707 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004708 /* we force the backend to be present on at least all of
4709 * the frontend's processes.
4710 */
4711 target->bind_proc = curproxy->bind_proc ?
4712 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004713 }
4714 }
4715 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004716
4717 /* find the target proxy for 'use_backend' rules */
4718 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004719 struct proxy *target;
4720
Alex Williams96532db2009-11-01 21:27:13 -05004721 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004722
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004723 if (!target) {
4724 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4725 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004726 cfgerr++;
4727 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004728 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4729 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004730 cfgerr++;
4731 } else {
4732 free((void *)rule->be.name);
4733 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004734 /* we force the backend to be present on at least all of
4735 * the frontend's processes.
4736 */
4737 target->bind_proc = curproxy->bind_proc ?
4738 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004739 }
4740 }
4741
Emeric Brunb982a3d2010-01-04 15:45:53 +01004742 /* find the target table for 'stick' rules */
4743 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4744 struct proxy *target;
4745
Emeric Brun1d33b292010-01-04 15:47:17 +01004746 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4747 if (mrule->flags & STK_IS_STORE)
4748 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4749
Emeric Brunb982a3d2010-01-04 15:45:53 +01004750 if (mrule->table.name)
4751 target = findproxy(mrule->table.name, PR_CAP_BE);
4752 else
4753 target = curproxy;
4754
4755 if (!target) {
4756 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4757 curproxy->id, mrule->table.name);
4758 cfgerr++;
4759 }
4760 else if (target->table.size == 0) {
4761 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4762 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4763 cfgerr++;
4764 }
4765 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4766 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4767 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4768 cfgerr++;
4769 }
4770 else {
4771 free((void *)mrule->table.name);
4772 mrule->table.t = &(target->table);
4773 }
4774 }
4775
4776 /* find the target table for 'store response' rules */
4777 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4778 struct proxy *target;
4779
Emeric Brun1d33b292010-01-04 15:47:17 +01004780 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4781
Emeric Brunb982a3d2010-01-04 15:45:53 +01004782 if (mrule->table.name)
4783 target = findproxy(mrule->table.name, PR_CAP_BE);
4784 else
4785 target = curproxy;
4786
4787 if (!target) {
4788 Alert("Proxy '%s': unable to find store table '%s'.\n",
4789 curproxy->id, mrule->table.name);
4790 cfgerr++;
4791 }
4792 else if (target->table.size == 0) {
4793 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4794 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4795 cfgerr++;
4796 }
4797 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4798 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4799 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4800 cfgerr++;
4801 }
4802 else {
4803 free((void *)mrule->table.name);
4804 mrule->table.t = &(target->table);
4805 }
4806 }
4807
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004808 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4809 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004810 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4811 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4812 "proxy", curproxy->id);
4813 cfgerr++;
4814 goto out_uri_auth_compat;
4815 }
4816
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004817 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004818 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004819 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004820 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004821
Willy Tarreau95fa4692010-02-01 13:05:50 +01004822 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4823 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004824
4825 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004826 uri_auth_compat_req[i++] = "realm";
4827 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4828 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004829
Willy Tarreau95fa4692010-02-01 13:05:50 +01004830 uri_auth_compat_req[i++] = "unless";
4831 uri_auth_compat_req[i++] = "{";
4832 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4833 uri_auth_compat_req[i++] = "}";
4834 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004835
Willy Tarreau95fa4692010-02-01 13:05:50 +01004836 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4837 if (!req_acl) {
4838 cfgerr++;
4839 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004840 }
4841
Willy Tarreau95fa4692010-02-01 13:05:50 +01004842 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4843
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004844 if (curproxy->uri_auth->auth_realm) {
4845 free(curproxy->uri_auth->auth_realm);
4846 curproxy->uri_auth->auth_realm = NULL;
4847 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004848
4849 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004850 }
4851out_uri_auth_compat:
4852
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004853 cfgerr += acl_find_targets(curproxy);
4854
Willy Tarreau2738a142006-07-08 17:28:09 +02004855 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004856 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004857 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004858 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004859 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004860 " | While not properly invalid, you will certainly encounter various problems\n"
4861 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004862 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004863 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004864 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004865 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004866
Willy Tarreau1fa31262007-12-03 00:36:16 +01004867 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4868 * We must still support older configurations, so let's find out whether those
4869 * parameters have been set or must be copied from contimeouts.
4870 */
4871 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004872 if (!curproxy->timeout.tarpit ||
4873 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004874 /* tarpit timeout not set. We search in the following order:
4875 * default.tarpit, curr.connect, default.connect.
4876 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004877 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004878 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004879 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004880 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004881 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004882 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004883 }
4884 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004885 (!curproxy->timeout.queue ||
4886 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004887 /* queue timeout not set. We search in the following order:
4888 * default.queue, curr.connect, default.connect.
4889 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004890 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004891 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004892 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004893 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004894 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004895 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004896 }
4897 }
4898
Willy Tarreauf3c69202006-07-09 16:42:34 +02004899 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004900 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4901 curproxy->check_req = (char *)malloc(curproxy->check_len);
4902 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004903 }
4904
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004905 /* The small pools required for the capture lists */
4906 if (curproxy->nb_req_cap)
4907 curproxy->req_cap_pool = create_pool("ptrcap",
4908 curproxy->nb_req_cap * sizeof(char *),
4909 MEM_F_SHARED);
4910 if (curproxy->nb_rsp_cap)
4911 curproxy->rsp_cap_pool = create_pool("ptrcap",
4912 curproxy->nb_rsp_cap * sizeof(char *),
4913 MEM_F_SHARED);
4914
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004915 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4916 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4917 MEM_F_SHARED);
4918
Willy Tarreau86034312006-12-29 00:10:33 +01004919 /* for backwards compatibility with "listen" instances, if
4920 * fullconn is not set but maxconn is set, then maxconn
4921 * is used.
4922 */
4923 if (!curproxy->fullconn)
4924 curproxy->fullconn = curproxy->maxconn;
4925
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 /* first, we will invert the servers list order */
4927 newsrv = NULL;
4928 while (curproxy->srv) {
4929 struct server *next;
4930
4931 next = curproxy->srv->next;
4932 curproxy->srv->next = newsrv;
4933 newsrv = curproxy->srv;
4934 if (!next)
4935 break;
4936 curproxy->srv = next;
4937 }
4938
Willy Tarreau20697042007-11-15 23:26:18 +01004939 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004940 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004942 /* We have to initialize the server lookup mechanism depending
4943 * on what LB algorithm was choosen.
4944 */
4945
4946 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4947 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4948 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004949 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4950 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4951 init_server_map(curproxy);
4952 } else {
4953 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4954 fwrr_init_server_groups(curproxy);
4955 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004956 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004957
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004958 case BE_LB_KIND_LC:
4959 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004960 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004961 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004962
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004963 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004964 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4965 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4966 chash_init_server_tree(curproxy);
4967 } else {
4968 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4969 init_server_map(curproxy);
4970 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004971 break;
4972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973
4974 if (curproxy->options & PR_O_LOGASAP)
4975 curproxy->to_log &= ~LW_BYTES;
4976
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004977 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4978 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4979 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4980 proxy_type_str(curproxy), curproxy->id);
4981 err_code |= ERR_WARN;
4982 }
4983
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004985 * ensure that we're not cross-dressing a TCP server into HTTP.
4986 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004987 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004988 newsrv = curproxy->srv;
4989 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004990 if (!newsrv->puid) {
4991 /* server ID not set, use automatic numbering with first
4992 * spare entry starting with next_svid.
4993 */
4994 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4995 newsrv->conf.id.key = newsrv->puid = next_id;
4996 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004997 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004998 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004999
Willy Tarreau21d2af32008-02-14 20:25:24 +01005000 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005001 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5002 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005003 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005004 }
5005 newsrv = newsrv->next;
5006 }
5007
5008 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 * If this server supports a maxconn parameter, it needs a dedicated
5010 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005011 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 */
5013 newsrv = curproxy->srv;
5014 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005015 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 /* Only 'minconn' was specified, or it was higher than or equal
5017 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5018 * this will avoid further useless expensive computations.
5019 */
5020 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005021 } else if (newsrv->maxconn && !newsrv->minconn) {
5022 /* minconn was not specified, so we set it to maxconn */
5023 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005024 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005025 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5026 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005027 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005030 if (newsrv->trackit) {
5031 struct proxy *px;
5032 struct server *srv;
5033 char *pname, *sname;
5034
5035 pname = newsrv->trackit;
5036 sname = strrchr(pname, '/');
5037
5038 if (sname)
5039 *sname++ = '\0';
5040 else {
5041 sname = pname;
5042 pname = NULL;
5043 }
5044
5045 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005046 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005047 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005048 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5049 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005050 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005051 cfgerr++;
5052 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005053 }
5054 } else
5055 px = curproxy;
5056
5057 srv = findserver(px, sname);
5058 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005059 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5060 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005061 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005062 cfgerr++;
5063 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005064 }
5065
5066 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005067 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005068 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005069 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005070 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005071 cfgerr++;
5072 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005073 }
5074
5075 if (curproxy != px &&
5076 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005077 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005078 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005079 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005080 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005081 cfgerr++;
5082 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005083 }
5084
5085 newsrv->tracked = srv;
5086 newsrv->tracknext = srv->tracknext;
5087 srv->tracknext = newsrv;
5088
5089 free(newsrv->trackit);
5090 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005091 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 newsrv = newsrv->next;
5093 }
5094
Willy Tarreauc1a21672009-08-16 22:37:44 +02005095 if (curproxy->cap & PR_CAP_FE) {
5096 if (curproxy->tcp_req.inspect_delay ||
5097 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5098 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5099
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005100 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005101 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005102 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005103 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005104
5105 /* both TCP and HTTP must check switching rules */
5106 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5107 }
5108
5109 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005110 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005111 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005112 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005113 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005114
Emeric Brunb982a3d2010-01-04 15:45:53 +01005115 /* init table on backend capabilities proxy */
5116 stktable_init(&curproxy->table);
5117
Willy Tarreauc1a21672009-08-16 22:37:44 +02005118 /* If the backend does requires RDP cookie persistence, we have to
5119 * enable the corresponding analyser.
5120 */
5121 if (curproxy->options2 & PR_O2_RDPC_PRST)
5122 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5123 }
5124
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005125 listener = NULL;
5126 while (curproxy->listen) {
5127 struct listener *next;
5128
5129 next = curproxy->listen->next;
5130 curproxy->listen->next = listener;
5131 listener = curproxy->listen;
5132
5133 if (!next)
5134 break;
5135
5136 curproxy->listen = next;
5137 }
5138
Willy Tarreaue6b98942007-10-29 01:09:36 +01005139 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005140 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005141 listener = curproxy->listen;
5142 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005143 if (!listener->luid) {
5144 /* listener ID not set, use automatic numbering with first
5145 * spare entry starting with next_luid.
5146 */
5147 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5148 listener->conf.id.key = listener->luid = next_id;
5149 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005150 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005151 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005152
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005153 /* enable separate counters */
5154 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5155 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5156 if (!listener->name) {
5157 sprintf(trash, "sock-%d", listener->luid);
5158 listener->name = strdup(trash);
5159 }
5160 }
5161
Willy Tarreaue6b98942007-10-29 01:09:36 +01005162 if (curproxy->options & PR_O_TCP_NOLING)
5163 listener->options |= LI_O_NOLINGER;
5164 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005165 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005166 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005167 listener->accept = event_accept;
5168 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005169 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005170 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005171
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005172 /* smart accept mode is automatic in HTTP mode */
5173 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5174 (curproxy->mode == PR_MODE_HTTP &&
5175 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5176 listener->options |= LI_O_NOQUICKACK;
5177
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005178 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005179 listener = listener->next;
5180 }
5181
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 curproxy = curproxy->next;
5183 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005184
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005185 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5186 struct auth_users *curuser;
5187 int g;
5188
5189 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5190 unsigned int group_mask = 0;
5191 char *group = NULL;
5192
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005193 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005194 continue;
5195
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005196 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005197
5198 for (g = 0; g < curuserlist->grpcnt; g++)
5199 if (!strcmp(curuserlist->groups[g], group))
5200 break;
5201
5202 if (g == curuserlist->grpcnt) {
5203 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5204 curuserlist->name, group, curuser->user);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 group_mask |= (1 << g);
5210 }
5211
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005212 free(curuser->u.groups);
5213 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005214 }
5215
5216 for (g = 0; g < curuserlist->grpcnt; g++) {
5217 char *user = NULL;
5218
5219 if (!curuserlist->groupusers[g])
5220 continue;
5221
5222 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5223 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5224 if (!strcmp(curuser->user, user))
5225 break;
5226
5227 if (!curuser) {
5228 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5229 curuserlist->name, user, curuserlist->groups[g]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
5233
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005234 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005235 }
5236
5237 free(curuserlist->groupusers[g]);
5238 }
5239
5240 free(curuserlist->groupusers);
5241
5242#ifdef DEBUG_AUTH
5243 for (g = 0; g < curuserlist->grpcnt; g++) {
5244 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5245
5246 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5247 if (curuser->group_mask & (1 << g))
5248 fprintf(stderr, " %s", curuser->user);
5249 }
5250
5251 fprintf(stderr, "\n");
5252 }
5253#endif
5254
5255 }
5256
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005257 /*
5258 * Recount currently required checks.
5259 */
5260
5261 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5262 int optnum;
5263
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005264 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5265 if (curproxy->options & cfg_opts[optnum].val)
5266 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005267
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005268 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5269 if (curproxy->options2 & cfg_opts2[optnum].val)
5270 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005271 }
5272
Willy Tarreaubb925012009-07-23 13:36:36 +02005273 if (cfgerr > 0)
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 out:
5276 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277}
5278
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005279/*
5280 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5281 * parsing sessions.
5282 */
5283void cfg_register_keywords(struct cfg_kw_list *kwl)
5284{
5285 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5286}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005288/*
5289 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5290 */
5291void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5292{
5293 LIST_DEL(&kwl->list);
5294 LIST_INIT(&kwl->list);
5295}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296
5297/*
5298 * Local variables:
5299 * c-indent-level: 8
5300 * c-basic-offset: 8
5301 * End:
5302 */