blob: b5437a6a1a5657184ec60d2ddec381e31ecd9384 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
730 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
731 break;
732 }
733
734 if (!i || args[1][i]) {
735 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
736 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
737 file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741
742 if (global.node)
743 free(global.node);
744
745 global.node = strdup(args[1]);
746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 else if (!strcmp(args[0], "pidfile")) {
748 if (global.pidfile != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.pidfile = strdup(args[1]);
759 }
760 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200762 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763
764 if (*(args[1]) == 0 || *(args[2]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769
770 facility = get_log_facility(args[2]);
771 if (facility < 0) {
772 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776
777 level = 7; /* max syslog level = debug */
778 if (*(args[3])) {
779 level = get_log_level(args[3]);
780 if (level < 0) {
781 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 }
786
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200787 minlvl = 0; /* limit syslog level to this level (emerg) */
788 if (*(args[4])) {
789 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200794 }
795 }
796
Robert Tsai81ae1952007-12-05 10:47:29 +0100797 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100798 struct sockaddr_un *sk = str2sun(args[1]);
799 if (!sk) {
800 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
801 args[1], (int)sizeof(sk->sun_path) - 1);
802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
804 }
805 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100806 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100807 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100808 struct sockaddr_in *sk = str2sa(args[1]);
809 if (!sk) {
810 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
811 err_code |= ERR_ALERT | ERR_FATAL;
812 goto out;
813 }
814 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100815 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100816 if (!logsrv.u.in.sin_port)
817 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
818 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819
820 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100821 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 global.logfac1 = facility;
823 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200824 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200825 }
826 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100827 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 global.logfac2 = facility;
829 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200830 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200831 }
832 else {
833 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200836 }
837 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
838 if (global.spread_checks != 0) {
839 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200840 err_code |= ERR_ALERT;
841 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200842 }
843 if (*(args[1]) == 0) {
844 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200847 }
848 global.spread_checks = atol(args[1]);
849 if (global.spread_checks < 0 || global.spread_checks > 50) {
850 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 }
854 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200855 struct cfg_kw_list *kwl;
856 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200857 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200858
859 list_for_each_entry(kwl, &cfg_keywords.list, list) {
860 for (index = 0; kwl->kw[index].kw != NULL; index++) {
861 if (kwl->kw[index].section != CFG_GLOBAL)
862 continue;
863 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
864 /* prepare error message just in case */
865 snprintf(trash, sizeof(trash),
866 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200867 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
868 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200869 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200871 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200872 else if (rc > 0) {
873 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200874 err_code |= ERR_WARN;
875 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200876 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200878 }
879 }
880 }
881
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200885
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 out:
887 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888}
889
Willy Tarreau97cb7802010-01-03 20:23:58 +0100890/* Perform the most basic initialization of a proxy :
891 * memset(), list_init(*), reset_timeouts(*).
892 */
893static void init_new_proxy(struct proxy *p)
894{
895 memset(p, 0, sizeof(struct proxy));
896 LIST_INIT(&p->pendconns);
897 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100898 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100899 LIST_INIT(&p->block_cond);
900 LIST_INIT(&p->redirect_rules);
901 LIST_INIT(&p->mon_fail_cond);
902 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100903 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100904 LIST_INIT(&p->sticking_rules);
905 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100906 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100907 LIST_INIT(&p->req_add);
908 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100909
910 /* Timeouts are defined as -1 */
911 proxy_reset_timeouts(p);
912}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200914void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100916 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 defproxy.mode = PR_MODE_TCP;
918 defproxy.state = PR_STNEW;
919 defproxy.maxconn = cfg_maxpconn;
920 defproxy.conn_retries = CONN_RETRIES;
921 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100922
923 defproxy.defsrv.inter = DEF_CHKINTR;
924 defproxy.defsrv.fastinter = 0;
925 defproxy.defsrv.downinter = 0;
926 defproxy.defsrv.rise = DEF_RISETIME;
927 defproxy.defsrv.fall = DEF_FALLTIME;
928 defproxy.defsrv.check_port = 0;
929 defproxy.defsrv.maxqueue = 0;
930 defproxy.defsrv.minconn = 0;
931 defproxy.defsrv.maxconn = 0;
932 defproxy.defsrv.slowstart = 0;
933 defproxy.defsrv.onerror = DEF_HANA_ONERR;
934 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
935 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936}
937
Willy Tarreauade5ec42010-01-28 19:33:49 +0100938
939static int create_cond_regex_rule(const char *file, int line,
940 struct proxy *px, int dir, int action, int flags,
941 const char *cmd, const char *reg, const char *repl,
942 const char **cond_start)
943{
944 regex_t *preg = NULL;
945 const char *err;
946 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100947 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100948
949 if (px == &defproxy) {
950 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto err;
953 }
954
955 if (*reg == 0) {
956 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto err;
959 }
960
961 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
962 err_code |= ERR_WARN;
963
Willy Tarreau5321c422010-01-28 20:35:13 +0100964 if (cond_start &&
965 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
966 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
967 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
968 file, line, cmd);
969 err_code |= ERR_ALERT | ERR_FATAL;
970 goto err;
971 }
972 }
973 else if (cond_start && **cond_start) {
974 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
975 file, line, cmd, *cond_start);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto err;
978 }
979
980 if (dir == ACL_DIR_REQ)
981 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100982 else
983 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100984
Willy Tarreauade5ec42010-01-28 19:33:49 +0100985 preg = calloc(1, sizeof(regex_t));
986 if (!preg) {
987 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
988 err_code = ERR_ALERT | ERR_FATAL;
989 goto err;
990 }
991
992 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
993 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
994 err_code = ERR_ALERT | ERR_FATAL;
995 goto err;
996 }
997
998 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100999 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001000 if (repl && err) {
1001 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1002 file, line, cmd, *err);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto err;
1005 }
1006
1007 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1008 err_code |= ERR_WARN;
1009
1010 return err_code;
1011 err:
1012 free(preg);
1013 return err_code;
1014}
1015
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001017 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001018 * Returns the error code, 0 if OK, or any combination of :
1019 * - ERR_ABORT: must abort ASAP
1020 * - ERR_FATAL: we can continue parsing but not start the service
1021 * - ERR_WARN: a warning has been emitted
1022 * - ERR_ALERT: an alert has been emitted
1023 * Only the two first ones can stop processing, the two others are just
1024 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001026int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027{
1028 static struct proxy *curproxy = NULL;
1029 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001030 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001031 int rc;
1032 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001033 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001034 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035
Willy Tarreau977b8e42006-12-29 14:19:17 +01001036 if (!strcmp(args[0], "listen"))
1037 rc = PR_CAP_LISTEN;
1038 else if (!strcmp(args[0], "frontend"))
1039 rc = PR_CAP_FE | PR_CAP_RS;
1040 else if (!strcmp(args[0], "backend"))
1041 rc = PR_CAP_BE | PR_CAP_RS;
1042 else if (!strcmp(args[0], "ruleset"))
1043 rc = PR_CAP_RS;
1044 else
1045 rc = PR_CAP_NONE;
1046
1047 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (!*args[1]) {
1049 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1050 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1051 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001052 err_code |= ERR_ALERT | ERR_ABORT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001055
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001056 err = invalid_char(args[1]);
1057 if (err) {
1058 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1059 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001060 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001061 }
1062
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001063 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1064 /*
1065 * If there are two proxies with the same name only following
1066 * combinations are allowed:
1067 *
1068 * listen backend frontend ruleset
1069 * listen - - - -
1070 * backend - - OK -
1071 * frontend - OK - -
1072 * ruleset - - - -
1073 */
1074
1075 if (!strcmp(curproxy->id, args[1]) &&
1076 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1077 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001078 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1079 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1080 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001081 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001082 }
1083 }
1084
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1086 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001087 err_code |= ERR_ALERT | ERR_ABORT;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001090
Willy Tarreau97cb7802010-01-03 20:23:58 +01001091 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 curproxy->next = proxy;
1093 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001094 curproxy->conf.file = file;
1095 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001096 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001098 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099
1100 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001101 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001102 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001103 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001104 err_code |= ERR_FATAL;
1105 goto out;
1106 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001107 new = curproxy->listen;
1108 while (new != last) {
1109 new->conf.file = file;
1110 new->conf.line = linenum;
1111 new = new->next;
1112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 global.maxsock++;
1114 }
1115
1116 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001117 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1118
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001121 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001122 curproxy->no_options = defproxy.no_options;
1123 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001124 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001125 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001126 curproxy->except_net = defproxy.except_net;
1127 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001128 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001129 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001131 if (defproxy.fwdfor_hdr_len) {
1132 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1133 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1134 }
1135
Willy Tarreaub86db342009-11-30 11:50:16 +01001136 if (defproxy.orgto_hdr_len) {
1137 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1138 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1139 }
1140
Willy Tarreau977b8e42006-12-29 14:19:17 +01001141 if (curproxy->cap & PR_CAP_FE) {
1142 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001143 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001144 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001145
1146 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001147 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1148 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001149
1150 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152
Willy Tarreau977b8e42006-12-29 14:19:17 +01001153 if (curproxy->cap & PR_CAP_BE) {
1154 curproxy->fullconn = defproxy.fullconn;
1155 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156
Willy Tarreau977b8e42006-12-29 14:19:17 +01001157 if (defproxy.check_req)
1158 curproxy->check_req = strdup(defproxy.check_req);
1159 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160
Willy Tarreau977b8e42006-12-29 14:19:17 +01001161 if (defproxy.cookie_name)
1162 curproxy->cookie_name = strdup(defproxy.cookie_name);
1163 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001164 if (defproxy.cookie_domain)
1165 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001166
Emeric Brun647caf12009-06-30 17:57:00 +02001167 if (defproxy.rdp_cookie_name)
1168 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1169 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1170
Willy Tarreau01732802007-11-01 22:48:15 +01001171 if (defproxy.url_param_name)
1172 curproxy->url_param_name = strdup(defproxy.url_param_name);
1173 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001174
Benoitaffb4812009-03-25 13:02:10 +01001175 if (defproxy.hh_name)
1176 curproxy->hh_name = strdup(defproxy.hh_name);
1177 curproxy->hh_len = defproxy.hh_len;
1178 curproxy->hh_match_domain = defproxy.hh_match_domain;
1179
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001180 if (defproxy.iface_name)
1181 curproxy->iface_name = strdup(defproxy.iface_name);
1182 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001185 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001186 if (defproxy.capture_name)
1187 curproxy->capture_name = strdup(defproxy.capture_name);
1188 curproxy->capture_namelen = defproxy.capture_namelen;
1189 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001193 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001194 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001195 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001196 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001197 curproxy->uri_auth = defproxy.uri_auth;
1198 curproxy->mon_net = defproxy.mon_net;
1199 curproxy->mon_mask = defproxy.mon_mask;
1200 if (defproxy.monitor_uri)
1201 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1202 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001203 if (defproxy.defbe.name)
1204 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001205 }
1206
1207 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001208 curproxy->timeout.connect = defproxy.timeout.connect;
1209 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001210 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001211 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001212 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001213 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001214 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001215 curproxy->source_addr = defproxy.source_addr;
1216 }
1217
Willy Tarreaubaaee002006-06-26 02:48:02 +02001218 curproxy->mode = defproxy.mode;
1219 curproxy->logfac1 = defproxy.logfac1;
1220 curproxy->logsrv1 = defproxy.logsrv1;
1221 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001222 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 curproxy->logfac2 = defproxy.logfac2;
1224 curproxy->logsrv2 = defproxy.logsrv2;
1225 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001226 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001228 curproxy->conf.used_listener_id = EB_ROOT;
1229 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001230
Willy Tarreau93893792009-07-23 13:19:11 +02001231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 }
1233 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1234 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001235 /* FIXME-20070101: we should do this too at the end of the
1236 * config parsing to free all default values.
1237 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001238 free(defproxy.check_req);
1239 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001240 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001241 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001242 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001243 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001244 free(defproxy.capture_name);
1245 free(defproxy.monitor_uri);
1246 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001247 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001248 free(defproxy.fwdfor_hdr_name);
1249 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001250 free(defproxy.orgto_hdr_name);
1251 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001252
Willy Tarreaua534fea2008-08-03 12:19:50 +02001253 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001254 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001255
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 /* we cannot free uri_auth because it might already be used */
1257 init_default_instance();
1258 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001259 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 }
1262 else if (curproxy == NULL) {
1263 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266 }
1267
Willy Tarreau977b8e42006-12-29 14:19:17 +01001268
1269 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001271 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001272 int cur_arg;
1273
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (curproxy == &defproxy) {
1275 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001278 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001279 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001280 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001281
1282 if (strchr(args[1], ':') == NULL) {
1283 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1284 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001288
1289 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001290 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
1293 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001294
Willy Tarreau90a570f2009-10-04 20:54:54 +02001295 new_listen = curproxy->listen;
1296 while (new_listen != last_listen) {
1297 new_listen->conf.file = file;
1298 new_listen->conf.line = linenum;
1299 new_listen = new_listen->next;
1300 }
1301
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001302 cur_arg = 2;
1303 while (*(args[cur_arg])) {
1304 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1305#ifdef SO_BINDTODEVICE
1306 struct listener *l;
1307
1308 if (!*args[cur_arg + 1]) {
1309 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001313 }
1314
1315 for (l = curproxy->listen; l != last_listen; l = l->next)
1316 l->interface = strdup(args[cur_arg + 1]);
1317
1318 global.last_checks |= LSTCHK_NETADM;
1319
1320 cur_arg += 2;
1321 continue;
1322#else
1323 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1324 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001327#endif
1328 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001329 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1330#ifdef TCP_MAXSEG
1331 struct listener *l;
1332 int mss;
1333
1334 if (!*args[cur_arg + 1]) {
1335 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001339 }
1340
1341 mss = str2uic(args[cur_arg + 1]);
1342 if (mss < 1 || mss > 65535) {
1343 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001347 }
1348
1349 for (l = curproxy->listen; l != last_listen; l = l->next)
1350 l->maxseg = mss;
1351
1352 cur_arg += 2;
1353 continue;
1354#else
1355 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1356 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001357 err_code |= ERR_ALERT | ERR_FATAL;
1358 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001359#endif
1360 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001361
1362 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1363#ifdef TCP_DEFER_ACCEPT
1364 struct listener *l;
1365
1366 for (l = curproxy->listen; l != last_listen; l = l->next)
1367 l->options |= LI_O_DEF_ACCEPT;
1368
1369 cur_arg ++;
1370 continue;
1371#else
1372 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1373 file, linenum, args[0], args[cur_arg]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376#endif
1377 }
1378
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001379 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001380#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381 struct listener *l;
1382
1383 for (l = curproxy->listen; l != last_listen; l = l->next)
1384 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001385
1386 cur_arg ++;
1387 continue;
1388#else
1389 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1390 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
1392 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001393#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001394 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001395
1396 if (!strcmp(args[cur_arg], "name")) {
1397 struct listener *l;
1398
1399 for (l = curproxy->listen; l != last_listen; l = l->next)
1400 l->name = strdup(args[cur_arg + 1]);
1401
1402 cur_arg += 2;
1403 continue;
1404 }
1405
1406 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001407 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001408 struct listener *l;
1409
1410 if (curproxy->listen->next != last_listen) {
1411 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1412 file, linenum, args[cur_arg]);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto out;
1415 }
1416
1417 if (!*args[cur_arg + 1]) {
1418 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1419 file, linenum, args[cur_arg]);
1420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
1422 }
1423
1424 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001425 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001426
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001427 if (curproxy->listen->luid <= 0) {
1428 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001429 file, linenum);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001434 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1435 if (node) {
1436 l = container_of(node, struct listener, conf.id);
1437 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1438 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1439 err_code |= ERR_ALERT | ERR_FATAL;
1440 goto out;
1441 }
1442 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1443
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001444 cur_arg += 2;
1445 continue;
1446 }
1447
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001448 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 +01001449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001450 err_code |= ERR_ALERT | ERR_FATAL;
1451 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 }
1456 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1457 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1458 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1459 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 /* flush useless bits */
1467 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001470 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001472 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473
Willy Tarreau1c47f852006-07-09 08:22:27 +02001474 if (!*args[1]) {
1475 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1476 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001477 err_code |= ERR_ALERT | ERR_FATAL;
1478 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001479 }
1480
Willy Tarreaua534fea2008-08-03 12:19:50 +02001481 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001482 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001483 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001484 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001485 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1486
Willy Tarreau93893792009-07-23 13:19:11 +02001487 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1490 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1491 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1492 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1493 else {
1494 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001495 err_code |= ERR_ALERT | ERR_FATAL;
1496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 }
1498 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001499 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001500 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001501
1502 if (curproxy == &defproxy) {
1503 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1504 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001505 err_code |= ERR_ALERT | ERR_FATAL;
1506 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001507 }
1508
1509 if (!*args[1]) {
1510 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1511 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001514 }
1515
1516 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001517 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001518
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001519 if (curproxy->uuid <= 0) {
1520 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001521 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001524 }
1525
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001526 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1527 if (node) {
1528 struct proxy *target = container_of(node, struct proxy, conf.id);
1529 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1530 file, linenum, proxy_type_str(curproxy), curproxy->id,
1531 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
1535 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001536 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001537 else if (!strcmp(args[0], "description")) {
1538 int i, len=0;
1539 char *d;
1540
Cyril Bonté99ed3272010-01-24 23:29:44 +01001541 if (curproxy == &defproxy) {
1542 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1543 file, linenum, args[0]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001548 if (!*args[1]) {
1549 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1550 file, linenum, args[0]);
1551 return -1;
1552 }
1553
1554 for(i=1; *args[i]; i++)
1555 len += strlen(args[i])+1;
1556
1557 d = (char *)calloc(1, len);
1558 curproxy->desc = d;
1559
1560 d += sprintf(d, "%s", args[1]);
1561 for(i=2; *args[i]; i++)
1562 d += sprintf(d, " %s", args[i]);
1563
1564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1566 curproxy->state = PR_STSTOPPED;
1567 }
1568 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1569 curproxy->state = PR_STNEW;
1570 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001571 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1572 int cur_arg = 1;
1573 unsigned int set = 0;
1574
1575 while (*args[cur_arg]) {
1576 int u;
1577 if (strcmp(args[cur_arg], "all") == 0) {
1578 set = 0;
1579 break;
1580 }
1581 else if (strcmp(args[cur_arg], "odd") == 0) {
1582 set |= 0x55555555;
1583 }
1584 else if (strcmp(args[cur_arg], "even") == 0) {
1585 set |= 0xAAAAAAAA;
1586 }
1587 else {
1588 u = str2uic(args[cur_arg]);
1589 if (u < 1 || u > 32) {
1590 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001592 err_code |= ERR_ALERT | ERR_FATAL;
1593 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001594 }
1595 if (u > global.nbproc) {
1596 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001598 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001599 }
1600 set |= 1 << (u - 1);
1601 }
1602 cur_arg++;
1603 }
1604 curproxy->bind_proc = set;
1605 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001606 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001607 if (curproxy == &defproxy) {
1608 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001609 err_code |= ERR_ALERT | ERR_FATAL;
1610 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001611 }
1612
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001613 err = invalid_char(args[1]);
1614 if (err) {
1615 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1616 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001617 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001618 }
1619
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001620 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1621 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1622 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001625 }
1626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1628 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629
Willy Tarreau977b8e42006-12-29 14:19:17 +01001630 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001631 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001632
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (*(args[1]) == 0) {
1634 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001639
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001640 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001641 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 curproxy->cookie_name = strdup(args[1]);
1643 curproxy->cookie_len = strlen(curproxy->cookie_name);
1644
1645 cur_arg = 2;
1646 while (*(args[cur_arg])) {
1647 if (!strcmp(args[cur_arg], "rewrite")) {
1648 curproxy->options |= PR_O_COOK_RW;
1649 }
1650 else if (!strcmp(args[cur_arg], "indirect")) {
1651 curproxy->options |= PR_O_COOK_IND;
1652 }
1653 else if (!strcmp(args[cur_arg], "insert")) {
1654 curproxy->options |= PR_O_COOK_INS;
1655 }
1656 else if (!strcmp(args[cur_arg], "nocache")) {
1657 curproxy->options |= PR_O_COOK_NOC;
1658 }
1659 else if (!strcmp(args[cur_arg], "postonly")) {
1660 curproxy->options |= PR_O_COOK_POST;
1661 }
1662 else if (!strcmp(args[cur_arg], "prefix")) {
1663 curproxy->options |= PR_O_COOK_PFX;
1664 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001665 else if (!strcmp(args[cur_arg], "domain")) {
1666 if (!*args[cur_arg + 1]) {
1667 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1668 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001671 }
1672
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001673 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001674 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001675 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1676 " dots nor does not start with a dot."
1677 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001678 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001679 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001680 }
1681
1682 err = invalid_domainchar(args[cur_arg + 1]);
1683 if (err) {
1684 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1685 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001688 }
1689
Willy Tarreau68a897b2009-12-03 23:28:34 +01001690 if (!curproxy->cookie_domain) {
1691 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1692 } else {
1693 /* one domain was already specified, add another one by
1694 * building the string which will be returned along with
1695 * the cookie.
1696 */
1697 char *new_ptr;
1698 int new_len = strlen(curproxy->cookie_domain) +
1699 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1700 new_ptr = malloc(new_len);
1701 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1702 free(curproxy->cookie_domain);
1703 curproxy->cookie_domain = new_ptr;
1704 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001705 cur_arg++;
1706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001708 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 cur_arg++;
1714 }
1715 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1716 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 }
1720
1721 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1722 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
1726 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001727 else if (!strcmp(args[0], "persist")) { /* persist */
1728 if (*(args[1]) == 0) {
1729 Alert("parsing [%s:%d] : missing persist method.\n",
1730 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001733 }
1734
1735 if (!strncmp(args[1], "rdp-cookie", 10)) {
1736 curproxy->options2 |= PR_O2_RDPC_PRST;
1737
Emeric Brunb982a3d2010-01-04 15:45:53 +01001738 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001739 const char *beg, *end;
1740
1741 beg = args[1] + 11;
1742 end = strchr(beg, ')');
1743
1744 if (!end || end == beg) {
1745 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1746 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001749 }
1750
1751 free(curproxy->rdp_cookie_name);
1752 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1753 curproxy->rdp_cookie_len = end-beg;
1754 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001755 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001756 free(curproxy->rdp_cookie_name);
1757 curproxy->rdp_cookie_name = strdup("msts");
1758 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1759 }
1760 else { /* syntax */
1761 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1762 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001765 }
1766 }
1767 else {
1768 Alert("parsing [%s:%d] : unknown persist method.\n",
1769 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001772 }
1773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001775 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001777 if (curproxy == &defproxy) {
1778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001785
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001787 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 }
1792 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001793 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 curproxy->appsession_name = strdup(args[1]);
1795 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1796 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001797 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1798 if (err) {
1799 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1800 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001803 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001804 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001805
Willy Tarreau51041c72007-09-09 21:56:53 +02001806 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1807 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001808 err_code |= ERR_ALERT | ERR_ABORT;
1809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001811
1812 cur_arg = 6;
1813 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001814 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1815 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001816 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001817 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001818 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001819 } else if (!strcmp(args[cur_arg], "prefix")) {
1820 curproxy->options2 |= PR_O2_AS_PFX;
1821 } else if (!strcmp(args[cur_arg], "mode")) {
1822 if (!*args[cur_arg + 1]) {
1823 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1824 file, linenum, args[0], args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828
1829 cur_arg++;
1830 if (!strcmp(args[cur_arg], "query-string")) {
1831 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1832 curproxy->options2 |= PR_O2_AS_M_QS;
1833 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1834 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1835 curproxy->options2 |= PR_O2_AS_M_PP;
1836 } else {
1837 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001842 cur_arg++;
1843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 } /* Url App Session */
1845 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001846 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001847 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001848
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001850 if (curproxy == &defproxy) {
1851 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
1854 }
1855
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856 if (*(args[4]) == 0) {
1857 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1858 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001862 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863 curproxy->capture_name = strdup(args[2]);
1864 curproxy->capture_namelen = strlen(curproxy->capture_name);
1865 curproxy->capture_len = atol(args[4]);
1866 if (curproxy->capture_len >= CAPTURE_LEN) {
1867 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1868 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001869 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 curproxy->capture_len = CAPTURE_LEN - 1;
1871 }
1872 curproxy->to_log |= LW_COOKIE;
1873 }
1874 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1875 struct cap_hdr *hdr;
1876
1877 if (curproxy == &defproxy) {
1878 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 +02001879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 }
1882
1883 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1884 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1885 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 }
1889
1890 hdr = calloc(sizeof(struct cap_hdr), 1);
1891 hdr->next = curproxy->req_cap;
1892 hdr->name = strdup(args[3]);
1893 hdr->namelen = strlen(args[3]);
1894 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001895 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 hdr->index = curproxy->nb_req_cap++;
1897 curproxy->req_cap = hdr;
1898 curproxy->to_log |= LW_REQHDR;
1899 }
1900 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1901 struct cap_hdr *hdr;
1902
1903 if (curproxy == &defproxy) {
1904 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 +02001905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 }
1908
1909 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1910 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1911 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 }
1915 hdr = calloc(sizeof(struct cap_hdr), 1);
1916 hdr->next = curproxy->rsp_cap;
1917 hdr->name = strdup(args[3]);
1918 hdr->namelen = strlen(args[3]);
1919 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001920 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 hdr->index = curproxy->nb_rsp_cap++;
1922 curproxy->rsp_cap = hdr;
1923 curproxy->to_log |= LW_RSPHDR;
1924 }
1925 else {
1926 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 }
1931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001933 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 if (*(args[1]) == 0) {
1937 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 }
1942 curproxy->conn_retries = atol(args[1]);
1943 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001944 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1945 struct req_acl_rule *req_acl;
1946
1947 if (curproxy == &defproxy) {
1948 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
1951 }
1952
1953
1954 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1955 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1956 file, linenum, args[0]);
1957 err_code |= ERR_WARN;
1958 }
1959
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001960 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001961
1962 if (!req_acl) {
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001967 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001968 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1969 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001970 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001971 if (curproxy == &defproxy) {
1972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_FATAL;
1974 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001975 }
1976
Willy Tarreauef6494c2010-01-28 17:12:36 +01001977 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001978 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1979 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001982 }
1983
Willy Tarreauef6494c2010-01-28 17:12:36 +01001984 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001985 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1986 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001989 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001990
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001991 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001992 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001993 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001994 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001995 struct redirect_rule *rule;
1996 int cur_arg;
1997 int type = REDIRECT_TYPE_NONE;
1998 int code = 302;
1999 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002000 char *cookie = NULL;
2001 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002002 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002003
Cyril Bonté99ed3272010-01-24 23:29:44 +01002004 if (curproxy == &defproxy) {
2005 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
2008 }
2009
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002010 cur_arg = 1;
2011 while (*(args[cur_arg])) {
2012 if (!strcmp(args[cur_arg], "location")) {
2013 if (!*args[cur_arg + 1]) {
2014 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2015 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002018 }
2019
2020 type = REDIRECT_TYPE_LOCATION;
2021 cur_arg++;
2022 destination = args[cur_arg];
2023 }
2024 else if (!strcmp(args[cur_arg], "prefix")) {
2025 if (!*args[cur_arg + 1]) {
2026 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2027 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002030 }
2031
2032 type = REDIRECT_TYPE_PREFIX;
2033 cur_arg++;
2034 destination = args[cur_arg];
2035 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002036 else if (!strcmp(args[cur_arg], "set-cookie")) {
2037 if (!*args[cur_arg + 1]) {
2038 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2039 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_ALERT | ERR_FATAL;
2041 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002042 }
2043
2044 cur_arg++;
2045 cookie = args[cur_arg];
2046 cookie_set = 1;
2047 }
2048 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2049 if (!*args[cur_arg + 1]) {
2050 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2051 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002054 }
2055
2056 cur_arg++;
2057 cookie = args[cur_arg];
2058 cookie_set = 0;
2059 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002060 else if (!strcmp(args[cur_arg],"code")) {
2061 if (!*args[cur_arg + 1]) {
2062 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002066 }
2067 cur_arg++;
2068 code = atol(args[cur_arg]);
2069 if (code < 301 || code > 303) {
2070 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2071 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002074 }
2075 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002076 else if (!strcmp(args[cur_arg],"drop-query")) {
2077 flags |= REDIRECT_FLAG_DROP_QS;
2078 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002079 else if (!strcmp(args[cur_arg],"append-slash")) {
2080 flags |= REDIRECT_FLAG_APPEND_SLASH;
2081 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002082 else if (strcmp(args[cur_arg], "if") == 0 ||
2083 strcmp(args[cur_arg], "unless") == 0) {
2084 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2085 if (!cond) {
2086 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2087 file, linenum, args[0]);
2088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
2090 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002091 break;
2092 }
2093 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002094 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 +02002095 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002098 }
2099 cur_arg++;
2100 }
2101
2102 if (type == REDIRECT_TYPE_NONE) {
2103 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002107 }
2108
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002109 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2110 rule->cond = cond;
2111 rule->rdr_str = strdup(destination);
2112 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002113 if (cookie) {
2114 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2115 * a clear consists in appending "; Max-Age=0" at the end.
2116 */
2117 rule->cookie_len = strlen(cookie);
2118 if (cookie_set)
2119 rule->cookie_str = strdup(cookie);
2120 else {
2121 rule->cookie_str = malloc(rule->cookie_len + 12);
2122 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2123 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2124 rule->cookie_len += 11;
2125 }
2126 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002127 rule->type = type;
2128 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002129 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002130 LIST_INIT(&rule->list);
2131 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002132 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002133 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002134 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002135 struct switching_rule *rule;
2136
Willy Tarreaub099aca2008-10-12 17:26:37 +02002137 if (curproxy == &defproxy) {
2138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002141 }
2142
Willy Tarreau55ea7572007-06-17 19:56:27 +02002143 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002145
2146 if (*(args[1]) == 0) {
2147 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002150 }
2151
Willy Tarreauef6494c2010-01-28 17:12:36 +01002152 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002153 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002157 }
2158
Willy Tarreauef6494c2010-01-28 17:12:36 +01002159 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002160 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002161 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002164 }
2165
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002166 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002167
Willy Tarreau55ea7572007-06-17 19:56:27 +02002168 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2169 rule->cond = cond;
2170 rule->be.name = strdup(args[1]);
2171 LIST_INIT(&rule->list);
2172 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2173 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002174 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002175 struct force_persist_rule *rule;
2176
2177 if (curproxy == &defproxy) {
2178 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182
2183 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2184 err_code |= ERR_WARN;
2185
Willy Tarreauef6494c2010-01-28 17:12:36 +01002186 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002187 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2188 file, linenum, args[0]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
Willy Tarreauef6494c2010-01-28 17:12:36 +01002193 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002194 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2195 file, linenum);
2196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
2198 }
2199
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002200 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002201
2202 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2203 rule->cond = cond;
2204 LIST_INIT(&rule->list);
2205 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2206 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002207 else if (!strcmp(args[0], "stick-table")) {
2208 int myidx = 1;
2209
2210 curproxy->table.type = (unsigned int)-1;
2211 while (*args[myidx]) {
2212 const char *err;
2213
2214 if (strcmp(args[myidx], "size") == 0) {
2215 myidx++;
2216 if (!*(args[myidx])) {
2217 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2218 file, linenum, args[myidx-1]);
2219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
2221 }
2222 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2223 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2224 file, linenum, *err, args[myidx-1]);
2225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
2227 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002228 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002229 }
2230 else if (strcmp(args[myidx], "expire") == 0) {
2231 myidx++;
2232 if (!*(args[myidx])) {
2233 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2234 file, linenum, args[myidx-1]);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
2237 }
2238 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2239 if (err) {
2240 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2241 file, linenum, *err, args[myidx-1]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002246 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002247 }
2248 else if (strcmp(args[myidx], "nopurge") == 0) {
2249 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002250 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002251 }
2252 else if (strcmp(args[myidx], "type") == 0) {
2253 myidx++;
2254 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2255 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2256 file, linenum, args[myidx]);
2257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
2259 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002260 /* myidx already points to next arg */
2261 }
2262 else {
2263 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2264 file, linenum, args[myidx]);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002268 }
2269
2270 if (!curproxy->table.size) {
2271 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2272 file, linenum);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
2277 if (curproxy->table.type == (unsigned int)-1) {
2278 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2279 file, linenum);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283 }
2284 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002285 struct sticking_rule *rule;
2286 struct pattern_expr *expr;
2287 int myidx = 0;
2288 const char *name = NULL;
2289 int flags;
2290
2291 if (curproxy == &defproxy) {
2292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
2295 }
2296
2297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2298 err_code |= ERR_WARN;
2299 goto out;
2300 }
2301
2302 myidx++;
2303 if ((strcmp(args[myidx], "store") == 0) ||
2304 (strcmp(args[myidx], "store-request") == 0)) {
2305 myidx++;
2306 flags = STK_IS_STORE;
2307 }
2308 else if (strcmp(args[myidx], "store-response") == 0) {
2309 myidx++;
2310 flags = STK_IS_STORE | STK_ON_RSP;
2311 }
2312 else if (strcmp(args[myidx], "match") == 0) {
2313 myidx++;
2314 flags = STK_IS_MATCH;
2315 }
2316 else if (strcmp(args[myidx], "on") == 0) {
2317 myidx++;
2318 flags = STK_IS_MATCH | STK_IS_STORE;
2319 }
2320 else {
2321 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325
2326 if (*(args[myidx]) == 0) {
2327 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
2332 expr = pattern_parse_expr(args, &myidx);
2333 if (!expr) {
2334 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
2339 if (flags & STK_ON_RSP) {
2340 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2341 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2342 file, linenum, args[0], expr->fetch->kw);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346 } else {
2347 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2348 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2349 file, linenum, args[0], expr->fetch->kw);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 }
2354
2355 if (strcmp(args[myidx], "table") == 0) {
2356 myidx++;
2357 name = args[myidx++];
2358 }
2359
Willy Tarreauef6494c2010-01-28 17:12:36 +01002360 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2361 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002362 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2363 file, linenum, args[0]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002367 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002368 else if (*(args[myidx])) {
2369 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2370 file, linenum, args[0], args[myidx]);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
2373 }
2374
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002375 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2376
Emeric Brunb982a3d2010-01-04 15:45:53 +01002377 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2378 rule->cond = cond;
2379 rule->expr = expr;
2380 rule->flags = flags;
2381 rule->table.name = name ? strdup(name) : NULL;
2382 LIST_INIT(&rule->list);
2383 if (flags & STK_ON_RSP)
2384 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2385 else
2386 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002391
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2393 curproxy->uri_auth = NULL; /* we must detach from the default config */
2394
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002395 if (!*args[1]) {
2396 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 } else if (!strcmp(args[1], "uri")) {
2398 if (*(args[2]) == 0) {
2399 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2403 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_ABORT;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
2407 } else if (!strcmp(args[1], "realm")) {
2408 if (*(args[2]) == 0) {
2409 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2413 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_ABORT;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002417 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002418 unsigned interval;
2419
2420 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2421 if (err) {
2422 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2423 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002426 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2427 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_ABORT;
2429 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002430 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002431 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2432 struct req_acl_rule *req_acl;
2433
2434 if (curproxy == &defproxy) {
2435 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
2440 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2441 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2442 err_code |= ERR_ALERT | ERR_ABORT;
2443 goto out;
2444 }
2445
2446 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2447 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2448 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2449 file, linenum, args[0]);
2450 err_code |= ERR_WARN;
2451 }
2452
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002453 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002454
2455 if (!req_acl) {
2456 err_code |= ERR_ALERT | ERR_ABORT;
2457 goto out;
2458 }
2459
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002460 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002461 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 } else if (!strcmp(args[1], "auth")) {
2464 if (*(args[2]) == 0) {
2465 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2469 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_ABORT;
2471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }
2473 } else if (!strcmp(args[1], "scope")) {
2474 if (*(args[2]) == 0) {
2475 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2479 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_ABORT;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
2483 } else if (!strcmp(args[1], "enable")) {
2484 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2485 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_ABORT;
2487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002489 } else if (!strcmp(args[1], "hide-version")) {
2490 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2491 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_ABORT;
2493 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002494 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002495 } else if (!strcmp(args[1], "show-legends")) {
2496 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2497 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2498 err_code |= ERR_ALERT | ERR_ABORT;
2499 goto out;
2500 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002501 } else if (!strcmp(args[1], "show-node")) {
2502
2503 if (*args[2]) {
2504 int i;
2505 char c;
2506
2507 for (i=0; args[2][i]; i++) {
2508 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002509 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002510 break;
2511 }
2512
2513 if (!i || args[2][i]) {
2514 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2515 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2516 file, linenum, args[0], args[1]);
2517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
2519 }
2520 }
2521
2522 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2523 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2524 err_code |= ERR_ALERT | ERR_ABORT;
2525 goto out;
2526 }
2527 } else if (!strcmp(args[1], "show-desc")) {
2528 char *desc = NULL;
2529
2530 if (*args[2]) {
2531 int i, len=0;
2532 char *d;
2533
2534 for(i=2; *args[i]; i++)
2535 len += strlen(args[i])+1;
2536
2537 desc = d = (char *)calloc(1, len);
2538
2539 d += sprintf(d, "%s", args[2]);
2540 for(i=3; *args[i]; i++)
2541 d += sprintf(d, " %s", args[i]);
2542 }
2543
2544 if (!*args[2] && !global.desc)
2545 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2546 file, linenum, args[1]);
2547 else {
2548 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2549 free(desc);
2550 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2551 err_code |= ERR_ALERT | ERR_ABORT;
2552 goto out;
2553 }
2554 free(desc);
2555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002557stats_error_parsing:
2558 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2559 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563 }
2564 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002565 int optnum;
2566
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002567 if (*(args[1]) == '\0') {
2568 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002573
2574 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2575 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002576 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2577 err_code |= ERR_WARN;
2578 goto out;
2579 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002580
Willy Tarreau3842f002009-06-14 11:39:52 +02002581 curproxy->no_options &= ~cfg_opts[optnum].val;
2582 curproxy->options &= ~cfg_opts[optnum].val;
2583
2584 switch (kwm) {
2585 case KWM_STD:
2586 curproxy->options |= cfg_opts[optnum].val;
2587 break;
2588 case KWM_NO:
2589 curproxy->no_options |= cfg_opts[optnum].val;
2590 break;
2591 case KWM_DEF: /* already cleared */
2592 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002593 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002594
Willy Tarreau93893792009-07-23 13:19:11 +02002595 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002596 }
2597 }
2598
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002599 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2600 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002601 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2602 err_code |= ERR_WARN;
2603 goto out;
2604 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002605
Willy Tarreau3842f002009-06-14 11:39:52 +02002606 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2607 curproxy->options2 &= ~cfg_opts2[optnum].val;
2608
2609 switch (kwm) {
2610 case KWM_STD:
2611 curproxy->options2 |= cfg_opts2[optnum].val;
2612 break;
2613 case KWM_NO:
2614 curproxy->no_options2 |= cfg_opts2[optnum].val;
2615 break;
2616 case KWM_DEF: /* already cleared */
2617 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002618 }
Willy Tarreau93893792009-07-23 13:19:11 +02002619 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002620 }
2621 }
2622
Willy Tarreau3842f002009-06-14 11:39:52 +02002623 if (kwm != KWM_STD) {
2624 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002625 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002628 }
2629
Emeric Brun3a058f32009-06-30 18:26:00 +02002630 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002632 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002634 if (*(args[2]) != '\0') {
2635 if (!strcmp(args[2], "clf")) {
2636 curproxy->options2 |= PR_O2_CLFLOG;
2637 } else {
2638 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002641 }
2642 }
2643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 else if (!strcmp(args[1], "tcplog"))
2645 /* generate a detailed TCP log */
2646 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 else if (!strcmp(args[1], "tcpka")) {
2648 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002649 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002651
2652 if (curproxy->cap & PR_CAP_FE)
2653 curproxy->options |= PR_O_TCP_CLI_KA;
2654 if (curproxy->cap & PR_CAP_BE)
2655 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 }
2657 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_WARN;
2660
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002662 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002663 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002664 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002665 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002666 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002667 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 if (!*args[2]) { /* no argument */
2669 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2670 curproxy->check_len = strlen(DEF_CHECK_REQ);
2671 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002672 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 curproxy->check_req = (char *)malloc(reqlen);
2674 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002675 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002677 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 if (*args[4])
2679 reqlen += strlen(args[4]);
2680 else
2681 reqlen += strlen("HTTP/1.0");
2682
2683 curproxy->check_req = (char *)malloc(reqlen);
2684 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002685 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002687 }
2688 else if (!strcmp(args[1], "ssl-hello-chk")) {
2689 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002690 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002692
Willy Tarreaua534fea2008-08-03 12:19:50 +02002693 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002694 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002695 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002696 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002697 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002698 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
Willy Tarreau23677902007-05-08 23:50:35 +02002700 else if (!strcmp(args[1], "smtpchk")) {
2701 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002702 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002703 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002704 curproxy->options &= ~PR_O_HTTP_CHK;
2705 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002706 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002707 curproxy->options |= PR_O_SMTP_CHK;
2708
2709 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2710 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2711 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2712 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2713 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2714 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2715 curproxy->check_req = (char *)malloc(reqlen);
2716 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2717 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2718 } else {
2719 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2720 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2721 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2722 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2723 }
2724 }
2725 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002726 else if (!strcmp(args[1], "mysql-check")) {
2727 /* use MYSQL request to check servers' health */
2728 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002729 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002730 curproxy->options &= ~PR_O_HTTP_CHK;
2731 curproxy->options &= ~PR_O_SSL3_CHK;
2732 curproxy->options &= ~PR_O_SMTP_CHK;
2733 curproxy->options2 |= PR_O2_MYSQL_CHK;
2734 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002735 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002736 int cur_arg;
2737
2738 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2739 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002740 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002741
2742 curproxy->options |= PR_O_FWDFOR;
2743
2744 free(curproxy->fwdfor_hdr_name);
2745 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2746 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2747
2748 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2749 cur_arg = 2;
2750 while (*(args[cur_arg])) {
2751 if (!strcmp(args[cur_arg], "except")) {
2752 /* suboption except - needs additional argument for it */
2753 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2754 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2755 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002758 }
2759 /* flush useless bits */
2760 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002761 cur_arg += 2;
2762 } else if (!strcmp(args[cur_arg], "header")) {
2763 /* suboption header - needs additional argument for it */
2764 if (*(args[cur_arg+1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002769 }
2770 free(curproxy->fwdfor_hdr_name);
2771 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2772 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2773 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002774 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002775 /* unknown suboption - catchall */
2776 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2777 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002780 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002781 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002782 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002783 else if (!strcmp(args[1], "originalto")) {
2784 int cur_arg;
2785
2786 /* insert x-original-to field, but not for the IP address listed as an except.
2787 * set default options (ie: bitfield, header name, etc)
2788 */
2789
2790 curproxy->options |= PR_O_ORGTO;
2791
2792 free(curproxy->orgto_hdr_name);
2793 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2794 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2795
2796 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2797 cur_arg = 2;
2798 while (*(args[cur_arg])) {
2799 if (!strcmp(args[cur_arg], "except")) {
2800 /* suboption except - needs additional argument for it */
2801 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2802 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2803 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002806 }
2807 /* flush useless bits */
2808 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2809 cur_arg += 2;
2810 } else if (!strcmp(args[cur_arg], "header")) {
2811 /* suboption header - needs additional argument for it */
2812 if (*(args[cur_arg+1]) == 0) {
2813 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2814 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002817 }
2818 free(curproxy->orgto_hdr_name);
2819 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2820 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2821 cur_arg += 2;
2822 } else {
2823 /* unknown suboption - catchall */
2824 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2825 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002828 }
2829 } /* end while loop */
2830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 else {
2832 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 }
Willy Tarreau93893792009-07-23 13:19:11 +02002836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002838 else if (!strcmp(args[0], "default_backend")) {
2839 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002841
2842 if (*(args[1]) == 0) {
2843 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002846 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002847 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002848 curproxy->defbe.name = strdup(args[1]);
2849 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002854 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2855 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 /* enable reconnections to dispatch */
2858 curproxy->options |= PR_O_REDISP;
2859 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002860 else if (!strcmp(args[0], "http-check")) {
2861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002863
2864 if (strcmp(args[1], "disable-on-404") == 0) {
2865 /* enable a graceful server shutdown on an HTTP 404 response */
2866 curproxy->options |= PR_O_DISABLE404;
2867 }
Willy Tarreauef781042010-01-27 11:53:01 +01002868 else if (strcmp(args[1], "send-state") == 0) {
2869 /* enable emission of the apparent state of a server in HTTP checks */
2870 curproxy->options2 |= PR_O2_CHK_SNDST;
2871 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002872 else {
2873 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002876 }
2877 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002878 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002879 if (curproxy == &defproxy) {
2880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002883 }
2884
Willy Tarreaub80c2302007-11-30 20:51:32 +01002885 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002887
2888 if (strcmp(args[1], "fail") == 0) {
2889 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002890 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002891 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2892 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002895 }
2896
Willy Tarreauef6494c2010-01-28 17:12:36 +01002897 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002898 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2899 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002902 }
2903 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2904 }
2905 else {
2906 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002909 }
2910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911#ifdef TPROXY
2912 else if (!strcmp(args[0], "transparent")) {
2913 /* enable transparent proxy connections */
2914 curproxy->options |= PR_O_TRANSP;
2915 }
2916#endif
2917 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002918 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 if (*(args[1]) == 0) {
2922 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
2926 curproxy->maxconn = atol(args[1]);
2927 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002928 else if (!strcmp(args[0], "backlog")) { /* backlog */
2929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002930 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002931
2932 if (*(args[1]) == 0) {
2933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002936 }
2937 curproxy->backlog = atol(args[1]);
2938 }
Willy Tarreau86034312006-12-29 00:10:33 +01002939 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002940 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002942
Willy Tarreau86034312006-12-29 00:10:33 +01002943 if (*(args[1]) == 0) {
2944 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002947 }
2948 curproxy->fullconn = atol(args[1]);
2949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2951 if (*(args[1]) == 0) {
2952 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002956 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2957 if (err) {
2958 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2959 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002962 }
2963 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 }
2965 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002966 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 if (curproxy == &defproxy) {
2968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002973 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002974
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 if (strchr(args[1], ':') == NULL) {
2976 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002980 sk = str2sa(args[1]);
2981 if (!sk) {
2982 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
2988 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002992 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002993 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2994 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002999 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3001 err_code |= ERR_WARN;
3002
3003 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3004 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3005 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3006 }
3007 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3008 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3009 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3010 }
3011 else {
3012 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003017 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003019 char *rport, *raddr;
3020 short realport = 0;
3021 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003023 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003028 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030
3031 if (!*args[2]) {
3032 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003037
3038 err = invalid_char(args[1]);
3039 if (err) {
3040 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3041 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003044 }
3045
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003046 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003047 struct sockaddr_in *sk;
3048
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003049 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3051 err_code |= ERR_ALERT | ERR_ABORT;
3052 goto out;
3053 }
3054
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003055 /* the servers are linked backwards first */
3056 newsrv->next = curproxy->srv;
3057 curproxy->srv = newsrv;
3058 newsrv->proxy = curproxy;
3059 newsrv->conf.file = file;
3060 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003062 LIST_INIT(&newsrv->pendconns);
3063 do_check = 0;
3064 newsrv->state = SRV_RUNNING; /* early server setup */
3065 newsrv->last_change = now.tv_sec;
3066 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003068 /* several ways to check the port component :
3069 * - IP => port=+0, relative
3070 * - IP: => port=+0, relative
3071 * - IP:N => port=N, absolute
3072 * - IP:+N => port=+N, relative
3073 * - IP:-N => port=-N, relative
3074 */
3075 raddr = strdup(args[2]);
3076 rport = strchr(raddr, ':');
3077 if (rport) {
3078 *rport++ = 0;
3079 realport = atol(rport);
3080 if (!isdigit((unsigned char)*rport))
3081 newsrv->state |= SRV_MAPPORTS;
3082 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003084
Willy Tarreaud5191e72010-02-09 20:50:45 +01003085 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003086 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003087 if (!sk) {
3088 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 newsrv->addr = *sk;
3093 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003094
3095 newsrv->check_port = curproxy->defsrv.check_port;
3096 newsrv->inter = curproxy->defsrv.inter;
3097 newsrv->fastinter = curproxy->defsrv.fastinter;
3098 newsrv->downinter = curproxy->defsrv.downinter;
3099 newsrv->rise = curproxy->defsrv.rise;
3100 newsrv->fall = curproxy->defsrv.fall;
3101 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3102 newsrv->minconn = curproxy->defsrv.minconn;
3103 newsrv->maxconn = curproxy->defsrv.maxconn;
3104 newsrv->slowstart = curproxy->defsrv.slowstart;
3105 newsrv->onerror = curproxy->defsrv.onerror;
3106 newsrv->consecutive_errors_limit
3107 = curproxy->defsrv.consecutive_errors_limit;
3108 newsrv->uweight = newsrv->iweight
3109 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003111 newsrv->curfd = -1; /* no health-check in progress */
3112 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003114 cur_arg = 3;
3115 } else {
3116 newsrv = &curproxy->defsrv;
3117 cur_arg = 1;
3118 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003121 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003122 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003123
3124 if (!*args[cur_arg + 1]) {
3125 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3126 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003129 }
3130
3131 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003132 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003133
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003134 if (newsrv->puid <= 0) {
3135 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003136 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003139 }
3140
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003141 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3142 if (node) {
3143 struct server *target = container_of(node, struct server, conf.id);
3144 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3145 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003150 cur_arg += 2;
3151 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003152 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 newsrv->cookie = strdup(args[cur_arg + 1]);
3154 newsrv->cklen = strlen(args[cur_arg + 1]);
3155 cur_arg += 2;
3156 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003157 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003158 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3159 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3160 cur_arg += 2;
3161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003163 if (!*args[cur_arg + 1]) {
3164 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3165 file, linenum, args[cur_arg]);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
3168 }
3169
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003171 if (newsrv->rise <= 0) {
3172 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3173 file, linenum, args[cur_arg]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 newsrv->health = newsrv->rise;
3179 cur_arg += 2;
3180 }
3181 else if (!strcmp(args[cur_arg], "fall")) {
3182 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003183
3184 if (!*args[cur_arg + 1]) {
3185 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3186 file, linenum, args[cur_arg]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
3190
3191 if (newsrv->fall <= 0) {
3192 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3193 file, linenum, args[cur_arg]);
3194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
3196 }
3197
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 cur_arg += 2;
3199 }
3200 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003201 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3202 if (err) {
3203 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3204 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003207 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003208 if (val <= 0) {
3209 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3210 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003213 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003214 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 cur_arg += 2;
3216 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003217 else if (!strcmp(args[cur_arg], "fastinter")) {
3218 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3219 if (err) {
3220 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3221 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003224 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003225 if (val <= 0) {
3226 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3227 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003230 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003231 newsrv->fastinter = val;
3232 cur_arg += 2;
3233 }
3234 else if (!strcmp(args[cur_arg], "downinter")) {
3235 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3236 if (err) {
3237 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3238 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003241 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003242 if (val <= 0) {
3243 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3244 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003247 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003248 newsrv->downinter = val;
3249 cur_arg += 2;
3250 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003251 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003252 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3253 if (!sk) {
3254 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003259 cur_arg += 2;
3260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 else if (!strcmp(args[cur_arg], "port")) {
3262 newsrv->check_port = atol(args[cur_arg + 1]);
3263 cur_arg += 2;
3264 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003265 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 newsrv->state |= SRV_BACKUP;
3267 cur_arg ++;
3268 }
3269 else if (!strcmp(args[cur_arg], "weight")) {
3270 int w;
3271 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003272 if (w < 0 || w > 256) {
3273 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003278 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 cur_arg += 2;
3280 }
3281 else if (!strcmp(args[cur_arg], "minconn")) {
3282 newsrv->minconn = atol(args[cur_arg + 1]);
3283 cur_arg += 2;
3284 }
3285 else if (!strcmp(args[cur_arg], "maxconn")) {
3286 newsrv->maxconn = atol(args[cur_arg + 1]);
3287 cur_arg += 2;
3288 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003289 else if (!strcmp(args[cur_arg], "maxqueue")) {
3290 newsrv->maxqueue = atol(args[cur_arg + 1]);
3291 cur_arg += 2;
3292 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003293 else if (!strcmp(args[cur_arg], "slowstart")) {
3294 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003295 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003296 if (err) {
3297 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3298 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003301 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003302 if (val <= 0) {
3303 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3304 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003307 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003308 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003309 cur_arg += 2;
3310 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003311 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003312
3313 if (!*args[cur_arg + 1]) {
3314 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3315 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003318 }
3319
3320 newsrv->trackit = strdup(args[cur_arg + 1]);
3321
3322 cur_arg += 2;
3323 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003324 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 global.maxsock++;
3326 do_check = 1;
3327 cur_arg += 1;
3328 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003329 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003330 if (!strcmp(args[cur_arg + 1], "none"))
3331 newsrv->observe = HANA_OBS_NONE;
3332 else if (!strcmp(args[cur_arg + 1], "layer4"))
3333 newsrv->observe = HANA_OBS_LAYER4;
3334 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3335 if (curproxy->mode != PR_MODE_HTTP) {
3336 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3337 file, linenum, args[cur_arg + 1]);
3338 err_code |= ERR_ALERT;
3339 }
3340 newsrv->observe = HANA_OBS_LAYER7;
3341 }
3342 else {
3343 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3344 "'l4events', 'http-responses' but get '%s'\n",
3345 file, linenum, args[cur_arg], args[cur_arg + 1]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349
3350 cur_arg += 2;
3351 }
3352 else if (!strcmp(args[cur_arg], "on-error")) {
3353 if (!strcmp(args[cur_arg + 1], "fastinter"))
3354 newsrv->onerror = HANA_ONERR_FASTINTER;
3355 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3356 newsrv->onerror = HANA_ONERR_FAILCHK;
3357 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3358 newsrv->onerror = HANA_ONERR_SUDDTH;
3359 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3360 newsrv->onerror = HANA_ONERR_MARKDWN;
3361 else {
3362 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3363 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3364 file, linenum, args[cur_arg], args[cur_arg + 1]);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
3367 }
3368
3369 cur_arg += 2;
3370 }
3371 else if (!strcmp(args[cur_arg], "error-limit")) {
3372 if (!*args[cur_arg + 1]) {
3373 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3374 file, linenum, args[cur_arg]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
3378
3379 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3380
3381 if (newsrv->consecutive_errors_limit <= 0) {
3382 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3383 file, linenum, args[cur_arg]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003388 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003389 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003390 struct sockaddr_in *sk;
3391
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003393#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003394 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003395 file, linenum, "source", "usesrc");
3396#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003397 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003399#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003404 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3405 if (!sk) {
3406 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003411
3412 if (port_low != port_high) {
3413 int i;
3414 if (port_low <= 0 || port_low > 65535 ||
3415 port_high <= 0 || port_high > 65535 ||
3416 port_low > port_high) {
3417 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3418 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003421 }
3422 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3423 for (i = 0; i < newsrv->sport_range->size; i++)
3424 newsrv->sport_range->ports[i] = port_low + i;
3425 }
3426
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003428 while (*(args[cur_arg])) {
3429 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003430#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3431#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003432 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3433 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3434 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003437 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003438#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003439 if (!*args[cur_arg + 1]) {
3440 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3441 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003444 }
3445 if (!strcmp(args[cur_arg + 1], "client")) {
3446 newsrv->state |= SRV_TPROXY_CLI;
3447 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3448 newsrv->state |= SRV_TPROXY_CIP;
3449 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003450 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3451 if (!sk) {
3452 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003457 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003458 }
3459 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003460#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003461 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003462#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003463 cur_arg += 2;
3464 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003465#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003466 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003467 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003470#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3471 } /* "usesrc" */
3472
3473 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3474#ifdef SO_BINDTODEVICE
3475 if (!*args[cur_arg + 1]) {
3476 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003480 }
3481 if (newsrv->iface_name)
3482 free(newsrv->iface_name);
3483
3484 newsrv->iface_name = strdup(args[cur_arg + 1]);
3485 newsrv->iface_len = strlen(newsrv->iface_name);
3486 global.last_checks |= LSTCHK_NETADM;
3487#else
3488 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3489 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003492#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003493 cur_arg += 2;
3494 continue;
3495 }
3496 /* this keyword in not an option of "source" */
3497 break;
3498 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003500 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003501 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3502 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003507 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003508 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 +01003509 file, linenum, newsrv->id);
3510 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003511 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 +01003512 file, linenum);
3513
Willy Tarreau93893792009-07-23 13:19:11 +02003514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 }
3517 }
3518
3519 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003520 if (newsrv->trackit) {
3521 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003525 }
3526
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003527 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3528 newsrv->check_port = newsrv->check_addr.sin_port;
3529
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3531 newsrv->check_port = realport; /* by default */
3532 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003533 /* not yet valid, because no port was set on
3534 * the server either. We'll check if we have
3535 * a known port on the first listener.
3536 */
3537 struct listener *l;
3538 l = curproxy->listen;
3539 if (l) {
3540 int port;
3541 port = (l->addr.ss_family == AF_INET6)
3542 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3543 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3544 newsrv->check_port = port;
3545 }
3546 }
3547 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3549 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003553
3554 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 newsrv->state |= SRV_CHECKED;
3556 }
3557
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003558 if (!defsrv) {
3559 if (newsrv->state & SRV_BACKUP)
3560 curproxy->srv_bck++;
3561 else
3562 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003563
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003564 newsrv->prev_state = newsrv->state;
3565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
3567 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003568 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 int facility;
3570
3571 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3572 curproxy->logfac1 = global.logfac1;
3573 curproxy->logsrv1 = global.logsrv1;
3574 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003575 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 curproxy->logfac2 = global.logfac2;
3577 curproxy->logsrv2 = global.logsrv2;
3578 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003579 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003582 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583
3584 facility = get_log_facility(args[2]);
3585 if (facility < 0) {
3586 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3587 exit(1);
3588 }
3589
3590 level = 7; /* max syslog level = debug */
3591 if (*(args[3])) {
3592 level = get_log_level(args[3]);
3593 if (level < 0) {
3594 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3595 exit(1);
3596 }
3597 }
3598
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003599 minlvl = 0; /* limit syslog level to this level (emerg) */
3600 if (*(args[4])) {
3601 minlvl = get_log_level(args[4]);
3602 if (level < 0) {
3603 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3604 exit(1);
3605 }
3606 }
3607
Robert Tsai81ae1952007-12-05 10:47:29 +01003608 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003609 struct sockaddr_un *sk = str2sun(args[1]);
3610 if (!sk) {
3611 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3612 args[1], (int)sizeof(sk->sun_path) - 1);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003617 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003618 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003619 struct sockaddr_in *sk = str2sa(args[1]);
3620 if (!sk) {
3621 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003626 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003627 if (!logsrv.u.in.sin_port) {
3628 logsrv.u.in.sin_port =
3629 htons(SYSLOG_PORT);
3630 }
3631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632
3633 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003634 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 curproxy->logfac1 = facility;
3636 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003637 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
3639 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003640 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 curproxy->logfac2 = facility;
3642 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003643 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645 else {
3646 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
3650 }
3651 else {
3652 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3653 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657 }
3658 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003659 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003660 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003661
Willy Tarreau977b8e42006-12-29 14:19:17 +01003662 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003666 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3667 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003668 err_code |= ERR_ALERT | ERR_FATAL;
3669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003671
3672 /* we must first clear any optional default setting */
3673 curproxy->options &= ~PR_O_TPXY_MASK;
3674 free(curproxy->iface_name);
3675 curproxy->iface_name = NULL;
3676 curproxy->iface_len = 0;
3677
Willy Tarreaud5191e72010-02-09 20:50:45 +01003678 sk = str2sa(args[1]);
3679 if (!sk) {
3680 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003686
3687 cur_arg = 2;
3688 while (*(args[cur_arg])) {
3689 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003690#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3691#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003692 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3693 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3694 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003697 }
3698#endif
3699 if (!*args[cur_arg + 1]) {
3700 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3701 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003704 }
3705
3706 if (!strcmp(args[cur_arg + 1], "client")) {
3707 curproxy->options |= PR_O_TPXY_CLI;
3708 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3709 curproxy->options |= PR_O_TPXY_CIP;
3710 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003711 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3712 if (!sk) {
3713 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003718 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003719 }
3720 global.last_checks |= LSTCHK_NETADM;
3721#if !defined(CONFIG_HAP_LINUX_TPROXY)
3722 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003723#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003724#else /* no TPROXY support */
3725 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003726 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003729#endif
3730 cur_arg += 2;
3731 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003732 }
3733
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003734 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3735#ifdef SO_BINDTODEVICE
3736 if (!*args[cur_arg + 1]) {
3737 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003741 }
3742 if (curproxy->iface_name)
3743 free(curproxy->iface_name);
3744
3745 curproxy->iface_name = strdup(args[cur_arg + 1]);
3746 curproxy->iface_len = strlen(curproxy->iface_name);
3747 global.last_checks |= LSTCHK_NETADM;
3748#else
3749 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3750 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003753#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003754 cur_arg += 2;
3755 continue;
3756 }
3757 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3758 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003763 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3764 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3765 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003770 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003776
3777 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3778 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003779 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003780 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
3783 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3785 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003786 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3792 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003793 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003796 }
3797 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3799 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 }
3804 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3806 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003807 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003811 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3813 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003816 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003817 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003818 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3820 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003821 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003823 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003824 }
3825 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3827 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003828 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003830 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003833 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003839
3840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3841 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003842 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 }
3846 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3848 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003849 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
3853 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3855 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003856 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3862 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3869 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003874 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3876 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003879 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003882 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003883
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 if (curproxy == &defproxy) {
3885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 if (*(args[1]) == 0) {
3893 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003897
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003898 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3899 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3900 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3901 file, linenum, args[0]);
3902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
3904 }
3905 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3906 }
3907 else if (*args[2]) {
3908 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3909 file, linenum, args[0], args[2]);
3910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
3912 }
3913
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003914 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003915 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003916 wl->s = strdup(args[1]);
3917 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003918 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 }
3920 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003921 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003927
Willy Tarreauade5ec42010-01-28 19:33:49 +01003928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3929 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003930 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
3934 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003935 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3936 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003937 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003938 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
3941 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3943 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003944 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 }
3948 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003949 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3951 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
3955
Willy Tarreauade5ec42010-01-28 19:33:49 +01003956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3957 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003958 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
3962 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003963 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3964 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003965 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003966 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
3969 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003970 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3971 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003972 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003973 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
3976 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003977 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003978
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 if (curproxy == &defproxy) {
3980 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003984 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 if (*(args[1]) == 0) {
3988 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 }
3992
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003993 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3994 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3995 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3996 file, linenum, args[0]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000 err_code |= warnif_cond_requires_req(cond, file, linenum);
4001 }
4002 else if (*args[2]) {
4003 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4004 file, linenum, args[0], args[2]);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004009 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004010 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004011 wl->s = strdup(args[1]);
4012 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
4014 else if (!strcmp(args[0], "errorloc") ||
4015 !strcmp(args[0], "errorloc302") ||
4016 !strcmp(args[0], "errorloc303")) { /* error location */
4017 int errnum, errlen;
4018 char *err;
4019
Willy Tarreau977b8e42006-12-29 14:19:17 +01004020 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004022
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004024 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 }
4028
4029 errnum = atol(args[1]);
4030 if (!strcmp(args[0], "errorloc303")) {
4031 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4032 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4033 } else {
4034 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4035 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4036 }
4037
Willy Tarreau0f772532006-12-23 20:51:41 +01004038 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4039 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004040 chunk_destroy(&curproxy->errmsg[rc]);
4041 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004042 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004045
4046 if (rc >= HTTP_ERR_SIZE) {
4047 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4048 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 free(err);
4050 }
4051 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004052 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4053 int errnum, errlen, fd;
4054 char *err;
4055 struct stat stat;
4056
4057 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004059
4060 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004061 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004064 }
4065
4066 fd = open(args[2], O_RDONLY);
4067 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4068 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4069 file, linenum, args[2], args[1]);
4070 if (fd >= 0)
4071 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004074 }
4075
Willy Tarreau27a674e2009-08-17 07:23:33 +02004076 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004077 errlen = stat.st_size;
4078 } else {
4079 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004080 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004081 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004082 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004083 }
4084
4085 err = malloc(errlen); /* malloc() must succeed during parsing */
4086 errnum = read(fd, err, errlen);
4087 if (errnum != errlen) {
4088 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4089 file, linenum, args[2], args[1]);
4090 close(fd);
4091 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004094 }
4095 close(fd);
4096
4097 errnum = atol(args[1]);
4098 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4099 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004100 chunk_destroy(&curproxy->errmsg[rc]);
4101 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004102 break;
4103 }
4104 }
4105
4106 if (rc >= HTTP_ERR_SIZE) {
4107 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4108 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004110 free(err);
4111 }
4112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004114 struct cfg_kw_list *kwl;
4115 int index;
4116
4117 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4118 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4119 if (kwl->kw[index].section != CFG_LISTEN)
4120 continue;
4121 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4122 /* prepare error message just in case */
4123 snprintf(trash, sizeof(trash),
4124 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004125 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4126 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004127 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004130 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004131 else if (rc > 0) {
4132 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_WARN;
4134 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004135 }
Willy Tarreau93893792009-07-23 13:19:11 +02004136 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004137 }
4138 }
4139 }
4140
Willy Tarreau6daf3432008-01-22 16:44:08 +01004141 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 }
Willy Tarreau93893792009-07-23 13:19:11 +02004145 out:
4146 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147}
4148
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004149int
4150cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4151{
4152
4153 int err_code = 0;
4154 const char *err;
4155
4156 if (!strcmp(args[0], "userlist")) { /* new userlist */
4157 struct userlist *newul;
4158
4159 if (!*args[1]) {
4160 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4161 file, linenum, args[0]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
4166 err = invalid_char(args[1]);
4167 if (err) {
4168 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4169 file, linenum, *err, args[0], args[1]);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173
4174 for (newul = userlist; newul; newul = newul->next)
4175 if (!strcmp(newul->name, args[1])) {
4176 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4177 file, linenum, args[1]);
4178 err_code |= ERR_WARN;
4179 goto out;
4180 }
4181
4182 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4183 if (!newul) {
4184 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4185 err_code |= ERR_ALERT | ERR_ABORT;
4186 goto out;
4187 }
4188
4189 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4190 newul->name = strdup(args[1]);
4191
4192 if (!newul->groupusers | !newul->name) {
4193 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4194 err_code |= ERR_ALERT | ERR_ABORT;
4195 goto out;
4196 }
4197
4198 newul->next = userlist;
4199 userlist = newul;
4200
4201 } else if (!strcmp(args[0], "group")) { /* new group */
4202 int cur_arg, i;
4203 const char *err;
4204
4205 if (!*args[1]) {
4206 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4207 file, linenum, args[0]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
4212 err = invalid_char(args[1]);
4213 if (err) {
4214 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4215 file, linenum, *err, args[0], args[1]);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 }
4219
4220 for(i = 0; i < userlist->grpcnt; i++)
4221 if (!strcmp(userlist->groups[i], args[1])) {
4222 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4223 file, linenum, args[1], userlist->name);
4224 err_code |= ERR_ALERT;
4225 goto out;
4226 }
4227
4228 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4229 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4230 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233 }
4234
4235 cur_arg = 2;
4236
4237 while (*args[cur_arg]) {
4238 if (!strcmp(args[cur_arg], "users")) {
4239 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4240 cur_arg += 2;
4241 continue;
4242 } else {
4243 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4244 file, linenum, args[0]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248 }
4249
4250 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4251 } else if (!strcmp(args[0], "user")) { /* new user */
4252 struct auth_users *newuser;
4253 int cur_arg;
4254
4255 if (!*args[1]) {
4256 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4257 file, linenum, args[0]);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261
4262 for (newuser = userlist->users; newuser; newuser = newuser->next)
4263 if (!strcmp(newuser->user, args[1])) {
4264 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4265 file, linenum, args[1], userlist->name);
4266 err_code |= ERR_ALERT;
4267 goto out;
4268 }
4269
4270 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4271 if (!newuser) {
4272 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4273 err_code |= ERR_ALERT | ERR_ABORT;
4274 goto out;
4275 }
4276
4277 newuser->user = strdup(args[1]);
4278
4279 newuser->next = userlist->users;
4280 userlist->users = newuser;
4281
4282 cur_arg = 2;
4283
4284 while (*args[cur_arg]) {
4285 if (!strcmp(args[cur_arg], "password")) {
4286#ifndef CONFIG_HAP_CRYPT
4287 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4288 file, linenum);
4289 err_code |= ERR_ALERT;
4290#endif
4291 newuser->pass = strdup(args[cur_arg + 1]);
4292 cur_arg += 2;
4293 continue;
4294 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4295 newuser->pass = strdup(args[cur_arg + 1]);
4296 newuser->flags |= AU_O_INSECURE;
4297 cur_arg += 2;
4298 continue;
4299 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004300 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004301 cur_arg += 2;
4302 continue;
4303 } else {
4304 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4305 file, linenum, args[0]);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309 }
4310 } else {
4311 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 }
4314
4315out:
4316 return err_code;
4317}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318
4319/*
4320 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004321 * Returns the error code, 0 if OK, or any combination of :
4322 * - ERR_ABORT: must abort ASAP
4323 * - ERR_FATAL: we can continue parsing but not start the service
4324 * - ERR_WARN: a warning has been emitted
4325 * - ERR_ALERT: an alert has been emitted
4326 * Only the two first ones can stop processing, the two others are just
4327 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004329int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004331 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 FILE *f;
4333 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004335 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 if ((f=fopen(file,"r")) == NULL)
4338 return -1;
4339
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004340 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004341 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004342 char *end;
4343 char *args[MAX_LINE_ARGS + 1];
4344 char *line = thisline;
4345
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 linenum++;
4347
4348 end = line + strlen(line);
4349
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004350 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4351 /* Check if we reached the limit and the last char is not \n.
4352 * Watch out for the last line without the terminating '\n'!
4353 */
4354 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004355 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004356 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004357 }
4358
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004360 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 line++;
4362
4363 arg = 0;
4364 args[arg] = line;
4365
4366 while (*line && arg < MAX_LINE_ARGS) {
4367 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4368 * C equivalent value. Other combinations left unchanged (eg: \1).
4369 */
4370 if (*line == '\\') {
4371 int skip = 0;
4372 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4373 *line = line[1];
4374 skip = 1;
4375 }
4376 else if (line[1] == 'r') {
4377 *line = '\r';
4378 skip = 1;
4379 }
4380 else if (line[1] == 'n') {
4381 *line = '\n';
4382 skip = 1;
4383 }
4384 else if (line[1] == 't') {
4385 *line = '\t';
4386 skip = 1;
4387 }
4388 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004389 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 unsigned char hex1, hex2;
4391 hex1 = toupper(line[2]) - '0';
4392 hex2 = toupper(line[3]) - '0';
4393 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4394 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4395 *line = (hex1<<4) + hex2;
4396 skip = 3;
4397 }
4398 else {
4399 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 }
4402 }
4403 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004404 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 end -= skip;
4406 }
4407 line++;
4408 }
4409 else if (*line == '#' || *line == '\n' || *line == '\r') {
4410 /* end of string, end of loop */
4411 *line = 0;
4412 break;
4413 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004414 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004416 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004417 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 line++;
4419 args[++arg] = line;
4420 }
4421 else {
4422 line++;
4423 }
4424 }
4425
4426 /* empty line */
4427 if (!**args)
4428 continue;
4429
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004430 if (*line) {
4431 /* we had to stop due to too many args.
4432 * Let's terminate the string, print the offending part then cut the
4433 * last arg.
4434 */
4435 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4436 line++;
4437 *line = '\0';
4438
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004439 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004440 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 args[arg] = line;
4443 }
4444
Willy Tarreau540abe42007-05-02 20:50:16 +02004445 /* zero out remaining args and ensure that at least one entry
4446 * is zeroed out.
4447 */
4448 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 args[arg] = line;
4450 }
4451
Willy Tarreau3842f002009-06-14 11:39:52 +02004452 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004453 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004454 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004455 for (arg=0; *args[arg+1]; arg++)
4456 args[arg] = args[arg+1]; // shift args after inversion
4457 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004458 else if (!strcmp(args[0], "default")) {
4459 kwm = KWM_DEF;
4460 for (arg=0; *args[arg+1]; arg++)
4461 args[arg] = args[arg+1]; // shift args after inversion
4462 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004463
Willy Tarreau3842f002009-06-14 11:39:52 +02004464 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4465 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004467 }
4468
Willy Tarreau977b8e42006-12-29 14:19:17 +01004469 if (!strcmp(args[0], "listen") ||
4470 !strcmp(args[0], "frontend") ||
4471 !strcmp(args[0], "backend") ||
4472 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004473 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004475 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004476 cursection = strdup(args[0]);
4477 }
4478 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004480 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004481 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004482 } else if (!strcmp(args[0], "userlist")) {
4483 confsect = CFG_USERLIST;
4484 free(cursection);
4485 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 /* else it's a section keyword */
4488
4489 switch (confsect) {
4490 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004491 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 break;
4493 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004494 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004496 case CFG_USERLIST:
4497 err_code |= cfg_parse_users(file, linenum, args, kwm);
4498 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004500 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004501 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004503
4504 if (err_code & ERR_ABORT)
4505 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004507 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004508 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004510 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004511}
4512
Willy Tarreaubb925012009-07-23 13:36:36 +02004513/*
4514 * Returns the error code, 0 if OK, or any combination of :
4515 * - ERR_ABORT: must abort ASAP
4516 * - ERR_FATAL: we can continue parsing but not start the service
4517 * - ERR_WARN: a warning has been emitted
4518 * - ERR_ALERT: an alert has been emitted
4519 * Only the two first ones can stop processing, the two others are just
4520 * indicators.
4521 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004522int check_config_validity()
4523{
4524 int cfgerr = 0;
4525 struct proxy *curproxy = NULL;
4526 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004527 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004528 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004529 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530
4531 /*
4532 * Now, check for the integrity of all that we have collected.
4533 */
4534
4535 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004536 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004538 /* first, we will invert the proxy list order */
4539 curproxy = NULL;
4540 while (proxy) {
4541 struct proxy *next;
4542
4543 next = proxy->next;
4544 proxy->next = curproxy;
4545 curproxy = proxy;
4546 if (!next)
4547 break;
4548 proxy = next;
4549 }
4550
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004552 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 }
4556
4557 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004558 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004559 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004560 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004561 unsigned int next_id;
4562
4563 if (!curproxy->uuid) {
4564 /* proxy ID not set, use automatic numbering with first
4565 * spare entry starting with next_pxid.
4566 */
4567 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4568 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4569 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004570 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004571 next_pxid++;
4572
Willy Tarreau55ea7572007-06-17 19:56:27 +02004573
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004575 /* ensure we don't keep listeners uselessly bound */
4576 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 curproxy = curproxy->next;
4578 continue;
4579 }
4580
Willy Tarreauff01a212009-03-15 13:46:16 +01004581 switch (curproxy->mode) {
4582 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004583 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004584 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004585 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4586 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004587 cfgerr++;
4588 }
4589
4590 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004591 Warning("config : servers will be ignored for %s '%s'.\n",
4592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004593 break;
4594
4595 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004596 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004597 break;
4598
4599 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004600 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004601 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004602 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4603 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004604 cfgerr++;
4605 }
4606 break;
4607 }
4608
4609 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004610 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 cfgerr++;
4613 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004614
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004615 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004616 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004617 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004618 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4619 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004620 cfgerr++;
4621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004623 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004624 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4625 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004626 cfgerr++;
4627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004629 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004630 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4631 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004632 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004633 }
4634 }
4635 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4636 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4637 /* If no LB algo is set in a backend, and we're not in
4638 * transparent mode, dispatch mode nor proxy mode, we
4639 * want to use balance roundrobin by default.
4640 */
4641 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4642 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 }
4644 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004645
Willy Tarreau82936582007-11-30 15:20:09 +01004646 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4647 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004648 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4649 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004650 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004651 }
4652
Willy Tarreauef781042010-01-27 11:53:01 +01004653 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4654 curproxy->options &= ~PR_O2_CHK_SNDST;
4655 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4656 "send-state", proxy_type_str(curproxy), curproxy->id);
4657 err_code |= ERR_WARN;
4658 }
4659
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004660 /* if a default backend was specified, let's find it */
4661 if (curproxy->defbe.name) {
4662 struct proxy *target;
4663
Alex Williams96532db2009-11-01 21:27:13 -05004664 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004665 if (!target) {
4666 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4667 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004668 cfgerr++;
4669 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004670 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4671 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004672 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004673 } else {
4674 free(curproxy->defbe.name);
4675 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004676 /* we force the backend to be present on at least all of
4677 * the frontend's processes.
4678 */
4679 target->bind_proc = curproxy->bind_proc ?
4680 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 }
4682 }
4683
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004684 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004685 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4686 /* map jump target for ACT_SETBE in req_rep chain */
4687 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004688 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004689 struct proxy *target;
4690
Willy Tarreaua496b602006-12-17 23:15:24 +01004691 if (exp->action != ACT_SETBE)
4692 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004693
Alex Williams96532db2009-11-01 21:27:13 -05004694 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004695 if (!target) {
4696 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4697 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004698 cfgerr++;
4699 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004700 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4701 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004702 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004703 } else {
4704 free((void *)exp->replace);
4705 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004706 /* we force the backend to be present on at least all of
4707 * the frontend's processes.
4708 */
4709 target->bind_proc = curproxy->bind_proc ?
4710 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004711 }
4712 }
4713 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004714
4715 /* find the target proxy for 'use_backend' rules */
4716 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004717 struct proxy *target;
4718
Alex Williams96532db2009-11-01 21:27:13 -05004719 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004720
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004721 if (!target) {
4722 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4723 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004724 cfgerr++;
4725 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004726 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4727 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004728 cfgerr++;
4729 } else {
4730 free((void *)rule->be.name);
4731 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004732 /* we force the backend to be present on at least all of
4733 * the frontend's processes.
4734 */
4735 target->bind_proc = curproxy->bind_proc ?
4736 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004737 }
4738 }
4739
Emeric Brunb982a3d2010-01-04 15:45:53 +01004740 /* find the target table for 'stick' rules */
4741 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4742 struct proxy *target;
4743
Emeric Brun1d33b292010-01-04 15:47:17 +01004744 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4745 if (mrule->flags & STK_IS_STORE)
4746 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4747
Emeric Brunb982a3d2010-01-04 15:45:53 +01004748 if (mrule->table.name)
4749 target = findproxy(mrule->table.name, PR_CAP_BE);
4750 else
4751 target = curproxy;
4752
4753 if (!target) {
4754 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4755 curproxy->id, mrule->table.name);
4756 cfgerr++;
4757 }
4758 else if (target->table.size == 0) {
4759 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4760 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4761 cfgerr++;
4762 }
4763 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4764 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4765 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4766 cfgerr++;
4767 }
4768 else {
4769 free((void *)mrule->table.name);
4770 mrule->table.t = &(target->table);
4771 }
4772 }
4773
4774 /* find the target table for 'store response' rules */
4775 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4776 struct proxy *target;
4777
Emeric Brun1d33b292010-01-04 15:47:17 +01004778 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4779
Emeric Brunb982a3d2010-01-04 15:45:53 +01004780 if (mrule->table.name)
4781 target = findproxy(mrule->table.name, PR_CAP_BE);
4782 else
4783 target = curproxy;
4784
4785 if (!target) {
4786 Alert("Proxy '%s': unable to find store table '%s'.\n",
4787 curproxy->id, mrule->table.name);
4788 cfgerr++;
4789 }
4790 else if (target->table.size == 0) {
4791 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4793 cfgerr++;
4794 }
4795 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4796 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4797 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4798 cfgerr++;
4799 }
4800 else {
4801 free((void *)mrule->table.name);
4802 mrule->table.t = &(target->table);
4803 }
4804 }
4805
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004806 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4807 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004808 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4809 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4810 "proxy", curproxy->id);
4811 cfgerr++;
4812 goto out_uri_auth_compat;
4813 }
4814
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004815 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004816 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004817 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004818 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004819
Willy Tarreau95fa4692010-02-01 13:05:50 +01004820 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4821 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004822
4823 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004824 uri_auth_compat_req[i++] = "realm";
4825 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4826 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004827
Willy Tarreau95fa4692010-02-01 13:05:50 +01004828 uri_auth_compat_req[i++] = "unless";
4829 uri_auth_compat_req[i++] = "{";
4830 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4831 uri_auth_compat_req[i++] = "}";
4832 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004833
Willy Tarreau95fa4692010-02-01 13:05:50 +01004834 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4835 if (!req_acl) {
4836 cfgerr++;
4837 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004838 }
4839
Willy Tarreau95fa4692010-02-01 13:05:50 +01004840 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4841
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004842 if (curproxy->uri_auth->auth_realm) {
4843 free(curproxy->uri_auth->auth_realm);
4844 curproxy->uri_auth->auth_realm = NULL;
4845 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004846
4847 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004848 }
4849out_uri_auth_compat:
4850
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004851 cfgerr += acl_find_targets(curproxy);
4852
Willy Tarreau2738a142006-07-08 17:28:09 +02004853 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004854 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004855 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004856 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004857 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004858 " | While not properly invalid, you will certainly encounter various problems\n"
4859 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004860 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004861 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004862 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004863 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004864
Willy Tarreau1fa31262007-12-03 00:36:16 +01004865 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4866 * We must still support older configurations, so let's find out whether those
4867 * parameters have been set or must be copied from contimeouts.
4868 */
4869 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004870 if (!curproxy->timeout.tarpit ||
4871 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004872 /* tarpit timeout not set. We search in the following order:
4873 * default.tarpit, curr.connect, default.connect.
4874 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004875 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004876 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004877 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004878 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004879 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004880 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004881 }
4882 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004883 (!curproxy->timeout.queue ||
4884 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004885 /* queue timeout not set. We search in the following order:
4886 * default.queue, curr.connect, default.connect.
4887 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004888 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004889 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004890 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004891 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004892 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004893 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004894 }
4895 }
4896
Willy Tarreauf3c69202006-07-09 16:42:34 +02004897 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004898 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4899 curproxy->check_req = (char *)malloc(curproxy->check_len);
4900 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004901 }
4902
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004903 /* The small pools required for the capture lists */
4904 if (curproxy->nb_req_cap)
4905 curproxy->req_cap_pool = create_pool("ptrcap",
4906 curproxy->nb_req_cap * sizeof(char *),
4907 MEM_F_SHARED);
4908 if (curproxy->nb_rsp_cap)
4909 curproxy->rsp_cap_pool = create_pool("ptrcap",
4910 curproxy->nb_rsp_cap * sizeof(char *),
4911 MEM_F_SHARED);
4912
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004913 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4914 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4915 MEM_F_SHARED);
4916
Willy Tarreau86034312006-12-29 00:10:33 +01004917 /* for backwards compatibility with "listen" instances, if
4918 * fullconn is not set but maxconn is set, then maxconn
4919 * is used.
4920 */
4921 if (!curproxy->fullconn)
4922 curproxy->fullconn = curproxy->maxconn;
4923
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 /* first, we will invert the servers list order */
4925 newsrv = NULL;
4926 while (curproxy->srv) {
4927 struct server *next;
4928
4929 next = curproxy->srv->next;
4930 curproxy->srv->next = newsrv;
4931 newsrv = curproxy->srv;
4932 if (!next)
4933 break;
4934 curproxy->srv = next;
4935 }
4936
Willy Tarreau20697042007-11-15 23:26:18 +01004937 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004938 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004940 /* We have to initialize the server lookup mechanism depending
4941 * on what LB algorithm was choosen.
4942 */
4943
4944 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4945 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4946 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004947 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4948 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4949 init_server_map(curproxy);
4950 } else {
4951 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4952 fwrr_init_server_groups(curproxy);
4953 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004954 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004955
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004956 case BE_LB_KIND_LC:
4957 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004958 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004959 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004960
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004961 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004962 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4963 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4964 chash_init_server_tree(curproxy);
4965 } else {
4966 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4967 init_server_map(curproxy);
4968 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004969 break;
4970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971
4972 if (curproxy->options & PR_O_LOGASAP)
4973 curproxy->to_log &= ~LW_BYTES;
4974
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004975 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4976 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4977 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4978 proxy_type_str(curproxy), curproxy->id);
4979 err_code |= ERR_WARN;
4980 }
4981
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004983 * ensure that we're not cross-dressing a TCP server into HTTP.
4984 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004985 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004986 newsrv = curproxy->srv;
4987 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004988 if (!newsrv->puid) {
4989 /* server ID not set, use automatic numbering with first
4990 * spare entry starting with next_svid.
4991 */
4992 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4993 newsrv->conf.id.key = newsrv->puid = next_id;
4994 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004995 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004996 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004997
Willy Tarreau21d2af32008-02-14 20:25:24 +01004998 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004999 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5000 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005001 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005002 }
5003 newsrv = newsrv->next;
5004 }
5005
5006 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 * If this server supports a maxconn parameter, it needs a dedicated
5008 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005009 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 */
5011 newsrv = curproxy->srv;
5012 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005013 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 /* Only 'minconn' was specified, or it was higher than or equal
5015 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5016 * this will avoid further useless expensive computations.
5017 */
5018 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005019 } else if (newsrv->maxconn && !newsrv->minconn) {
5020 /* minconn was not specified, so we set it to maxconn */
5021 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005022 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005023 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5024 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005025 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
5027
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005028 if (newsrv->trackit) {
5029 struct proxy *px;
5030 struct server *srv;
5031 char *pname, *sname;
5032
5033 pname = newsrv->trackit;
5034 sname = strrchr(pname, '/');
5035
5036 if (sname)
5037 *sname++ = '\0';
5038 else {
5039 sname = pname;
5040 pname = NULL;
5041 }
5042
5043 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005044 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005045 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005046 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5047 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005048 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005049 cfgerr++;
5050 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005051 }
5052 } else
5053 px = curproxy;
5054
5055 srv = findserver(px, sname);
5056 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005057 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5058 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005059 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005060 cfgerr++;
5061 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005062 }
5063
5064 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005065 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005066 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005067 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005068 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005069 cfgerr++;
5070 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005071 }
5072
5073 if (curproxy != px &&
5074 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005075 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005076 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005077 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005078 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005079 cfgerr++;
5080 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005081 }
5082
5083 newsrv->tracked = srv;
5084 newsrv->tracknext = srv->tracknext;
5085 srv->tracknext = newsrv;
5086
5087 free(newsrv->trackit);
5088 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005089 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 newsrv = newsrv->next;
5091 }
5092
Willy Tarreauc1a21672009-08-16 22:37:44 +02005093 if (curproxy->cap & PR_CAP_FE) {
5094 if (curproxy->tcp_req.inspect_delay ||
5095 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5096 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5097
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005098 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005099 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005100 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005101 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005102
5103 /* both TCP and HTTP must check switching rules */
5104 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5105 }
5106
5107 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005108 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005109 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005110 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005111 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005112
Emeric Brunb982a3d2010-01-04 15:45:53 +01005113 /* init table on backend capabilities proxy */
5114 stktable_init(&curproxy->table);
5115
Willy Tarreauc1a21672009-08-16 22:37:44 +02005116 /* If the backend does requires RDP cookie persistence, we have to
5117 * enable the corresponding analyser.
5118 */
5119 if (curproxy->options2 & PR_O2_RDPC_PRST)
5120 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5121 }
5122
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005123 listener = NULL;
5124 while (curproxy->listen) {
5125 struct listener *next;
5126
5127 next = curproxy->listen->next;
5128 curproxy->listen->next = listener;
5129 listener = curproxy->listen;
5130
5131 if (!next)
5132 break;
5133
5134 curproxy->listen = next;
5135 }
5136
Willy Tarreaue6b98942007-10-29 01:09:36 +01005137 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005138 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005139 listener = curproxy->listen;
5140 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005141 if (!listener->luid) {
5142 /* listener ID not set, use automatic numbering with first
5143 * spare entry starting with next_luid.
5144 */
5145 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5146 listener->conf.id.key = listener->luid = next_id;
5147 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005148 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005149 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005150
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005151 /* enable separate counters */
5152 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5153 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5154 if (!listener->name) {
5155 sprintf(trash, "sock-%d", listener->luid);
5156 listener->name = strdup(trash);
5157 }
5158 }
5159
Willy Tarreaue6b98942007-10-29 01:09:36 +01005160 if (curproxy->options & PR_O_TCP_NOLING)
5161 listener->options |= LI_O_NOLINGER;
5162 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005163 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005164 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005165 listener->accept = event_accept;
5166 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005167 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005168 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005169
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005170 /* smart accept mode is automatic in HTTP mode */
5171 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5172 (curproxy->mode == PR_MODE_HTTP &&
5173 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5174 listener->options |= LI_O_NOQUICKACK;
5175
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005176 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005177 listener = listener->next;
5178 }
5179
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 curproxy = curproxy->next;
5181 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005182
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005183 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5184 struct auth_users *curuser;
5185 int g;
5186
5187 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5188 unsigned int group_mask = 0;
5189 char *group = NULL;
5190
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005191 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005192 continue;
5193
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005194 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005195
5196 for (g = 0; g < curuserlist->grpcnt; g++)
5197 if (!strcmp(curuserlist->groups[g], group))
5198 break;
5199
5200 if (g == curuserlist->grpcnt) {
5201 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5202 curuserlist->name, group, curuser->user);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206
5207 group_mask |= (1 << g);
5208 }
5209
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005210 free(curuser->u.groups);
5211 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005212 }
5213
5214 for (g = 0; g < curuserlist->grpcnt; g++) {
5215 char *user = NULL;
5216
5217 if (!curuserlist->groupusers[g])
5218 continue;
5219
5220 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5221 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5222 if (!strcmp(curuser->user, user))
5223 break;
5224
5225 if (!curuser) {
5226 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5227 curuserlist->name, user, curuserlist->groups[g]);
5228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230 }
5231
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005232 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005233 }
5234
5235 free(curuserlist->groupusers[g]);
5236 }
5237
5238 free(curuserlist->groupusers);
5239
5240#ifdef DEBUG_AUTH
5241 for (g = 0; g < curuserlist->grpcnt; g++) {
5242 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5243
5244 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5245 if (curuser->group_mask & (1 << g))
5246 fprintf(stderr, " %s", curuser->user);
5247 }
5248
5249 fprintf(stderr, "\n");
5250 }
5251#endif
5252
5253 }
5254
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005255 /*
5256 * Recount currently required checks.
5257 */
5258
5259 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5260 int optnum;
5261
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005262 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5263 if (curproxy->options & cfg_opts[optnum].val)
5264 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005265
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005266 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5267 if (curproxy->options2 & cfg_opts2[optnum].val)
5268 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005269 }
5270
Willy Tarreaubb925012009-07-23 13:36:36 +02005271 if (cfgerr > 0)
5272 err_code |= ERR_ALERT | ERR_FATAL;
5273 out:
5274 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275}
5276
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005277/*
5278 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5279 * parsing sessions.
5280 */
5281void cfg_register_keywords(struct cfg_kw_list *kwl)
5282{
5283 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5284}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005286/*
5287 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5288 */
5289void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5290{
5291 LIST_DEL(&kwl->list);
5292 LIST_INIT(&kwl->list);
5293}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294
5295/*
5296 * Local variables:
5297 * c-indent-level: 8
5298 * c-basic-offset: 8
5299 * End:
5300 */