blob: 799188b5fca5f111ed0bcdd7293ab225ca124e4c [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100730 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
731 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200732 break;
733 }
734
735 if (!i || args[1][i]) {
736 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
737 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742
743 if (global.node)
744 free(global.node);
745
746 global.node = strdup(args[1]);
747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 else if (!strcmp(args[0], "pidfile")) {
749 if (global.pidfile != NULL) {
750 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT;
752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 }
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 global.pidfile = strdup(args[1]);
760 }
761 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100762 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200763 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764
765 if (*(args[1]) == 0 || *(args[2]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770
771 facility = get_log_facility(args[2]);
772 if (facility < 0) {
773 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777
778 level = 7; /* max syslog level = debug */
779 if (*(args[3])) {
780 level = get_log_level(args[3]);
781 if (level < 0) {
782 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT | ERR_FATAL;
784 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
786 }
787
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200788 minlvl = 0; /* limit syslog level to this level (emerg) */
789 if (*(args[4])) {
790 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200792 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
794 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200795 }
796 }
797
Robert Tsai81ae1952007-12-05 10:47:29 +0100798 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100799 struct sockaddr_un *sk = str2sun(args[1]);
800 if (!sk) {
801 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
802 args[1], (int)sizeof(sk->sun_path) - 1);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100807 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100809 struct sockaddr_in *sk = str2sa(args[1]);
810 if (!sk) {
811 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100816 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100817 if (!logsrv.u.in.sin_port)
818 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820
821 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100822 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 global.logfac1 = facility;
824 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200825 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100828 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 global.logfac2 = facility;
830 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200831 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 else {
834 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200837 }
838 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
839 if (global.spread_checks != 0) {
840 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT;
842 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200848 }
849 global.spread_checks = atol(args[1]);
850 if (global.spread_checks < 0 || global.spread_checks > 50) {
851 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200852 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 }
855 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 struct cfg_kw_list *kwl;
857 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200858 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200859
860 list_for_each_entry(kwl, &cfg_keywords.list, list) {
861 for (index = 0; kwl->kw[index].kw != NULL; index++) {
862 if (kwl->kw[index].section != CFG_GLOBAL)
863 continue;
864 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
865 /* prepare error message just in case */
866 snprintf(trash, sizeof(trash),
867 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200868 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
869 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200870 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200871 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200872 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200873 else if (rc > 0) {
874 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200875 err_code |= ERR_WARN;
876 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200877 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200879 }
880 }
881 }
882
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200886
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 out:
888 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
Willy Tarreau97cb7802010-01-03 20:23:58 +0100891/* Perform the most basic initialization of a proxy :
892 * memset(), list_init(*), reset_timeouts(*).
893 */
894static void init_new_proxy(struct proxy *p)
895{
896 memset(p, 0, sizeof(struct proxy));
897 LIST_INIT(&p->pendconns);
898 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100899 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100900 LIST_INIT(&p->block_cond);
901 LIST_INIT(&p->redirect_rules);
902 LIST_INIT(&p->mon_fail_cond);
903 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100904 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100905 LIST_INIT(&p->sticking_rules);
906 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100907 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100908 LIST_INIT(&p->req_add);
909 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100910
911 /* Timeouts are defined as -1 */
912 proxy_reset_timeouts(p);
913}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200915void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100917 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 defproxy.mode = PR_MODE_TCP;
919 defproxy.state = PR_STNEW;
920 defproxy.maxconn = cfg_maxpconn;
921 defproxy.conn_retries = CONN_RETRIES;
922 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100923
924 defproxy.defsrv.inter = DEF_CHKINTR;
925 defproxy.defsrv.fastinter = 0;
926 defproxy.defsrv.downinter = 0;
927 defproxy.defsrv.rise = DEF_RISETIME;
928 defproxy.defsrv.fall = DEF_FALLTIME;
929 defproxy.defsrv.check_port = 0;
930 defproxy.defsrv.maxqueue = 0;
931 defproxy.defsrv.minconn = 0;
932 defproxy.defsrv.maxconn = 0;
933 defproxy.defsrv.slowstart = 0;
934 defproxy.defsrv.onerror = DEF_HANA_ONERR;
935 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
936 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937}
938
Willy Tarreauade5ec42010-01-28 19:33:49 +0100939
940static int create_cond_regex_rule(const char *file, int line,
941 struct proxy *px, int dir, int action, int flags,
942 const char *cmd, const char *reg, const char *repl,
943 const char **cond_start)
944{
945 regex_t *preg = NULL;
946 const char *err;
947 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100948 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100949
950 if (px == &defproxy) {
951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto err;
954 }
955
956 if (*reg == 0) {
957 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto err;
960 }
961
962 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
963 err_code |= ERR_WARN;
964
Willy Tarreau5321c422010-01-28 20:35:13 +0100965 if (cond_start &&
966 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
967 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
968 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
969 file, line, cmd);
970 err_code |= ERR_ALERT | ERR_FATAL;
971 goto err;
972 }
973 }
974 else if (cond_start && **cond_start) {
975 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
976 file, line, cmd, *cond_start);
977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto err;
979 }
980
981 if (dir == ACL_DIR_REQ)
982 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100983 else
984 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100985
Willy Tarreauade5ec42010-01-28 19:33:49 +0100986 preg = calloc(1, sizeof(regex_t));
987 if (!preg) {
988 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
989 err_code = ERR_ALERT | ERR_FATAL;
990 goto err;
991 }
992
993 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
994 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
995 err_code = ERR_ALERT | ERR_FATAL;
996 goto err;
997 }
998
999 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001000 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001001 if (repl && err) {
1002 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1003 file, line, cmd, *err);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto err;
1006 }
1007
1008 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1009 err_code |= ERR_WARN;
1010
1011 return err_code;
1012 err:
1013 free(preg);
1014 return err_code;
1015}
1016
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001019 * Returns the error code, 0 if OK, or any combination of :
1020 * - ERR_ABORT: must abort ASAP
1021 * - ERR_FATAL: we can continue parsing but not start the service
1022 * - ERR_WARN: a warning has been emitted
1023 * - ERR_ALERT: an alert has been emitted
1024 * Only the two first ones can stop processing, the two others are just
1025 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001027int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028{
1029 static struct proxy *curproxy = NULL;
1030 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001031 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001032 int rc;
1033 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001034 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001035 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036
Willy Tarreau977b8e42006-12-29 14:19:17 +01001037 if (!strcmp(args[0], "listen"))
1038 rc = PR_CAP_LISTEN;
1039 else if (!strcmp(args[0], "frontend"))
1040 rc = PR_CAP_FE | PR_CAP_RS;
1041 else if (!strcmp(args[0], "backend"))
1042 rc = PR_CAP_BE | PR_CAP_RS;
1043 else if (!strcmp(args[0], "ruleset"))
1044 rc = PR_CAP_RS;
1045 else
1046 rc = PR_CAP_NONE;
1047
1048 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (!*args[1]) {
1050 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1051 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001053 err_code |= ERR_ALERT | ERR_ABORT;
1054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001056
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001057 err = invalid_char(args[1]);
1058 if (err) {
1059 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1060 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001062 }
1063
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001064 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1065 /*
1066 * If there are two proxies with the same name only following
1067 * combinations are allowed:
1068 *
1069 * listen backend frontend ruleset
1070 * listen - - - -
1071 * backend - - OK -
1072 * frontend - OK - -
1073 * ruleset - - - -
1074 */
1075
1076 if (!strcmp(curproxy->id, args[1]) &&
1077 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1078 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001079 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1080 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1081 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001082 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001083 }
1084 }
1085
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1087 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001088 err_code |= ERR_ALERT | ERR_ABORT;
1089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001091
Willy Tarreau97cb7802010-01-03 20:23:58 +01001092 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 curproxy->next = proxy;
1094 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001095 curproxy->conf.file = file;
1096 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001097 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001099 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100
1101 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001102 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001103 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001104 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001105 err_code |= ERR_FATAL;
1106 goto out;
1107 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 new = curproxy->listen;
1109 while (new != last) {
1110 new->conf.file = file;
1111 new->conf.line = linenum;
1112 new = new->next;
1113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 global.maxsock++;
1115 }
1116
1117 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001118 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001122 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001123 curproxy->no_options = defproxy.no_options;
1124 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001125 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001126 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001127 curproxy->except_net = defproxy.except_net;
1128 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001129 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001130 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001132 if (defproxy.fwdfor_hdr_len) {
1133 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1134 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1135 }
1136
Willy Tarreaub86db342009-11-30 11:50:16 +01001137 if (defproxy.orgto_hdr_len) {
1138 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1139 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1140 }
1141
Willy Tarreau977b8e42006-12-29 14:19:17 +01001142 if (curproxy->cap & PR_CAP_FE) {
1143 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001144 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001145 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146
1147 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001148 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1149 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150
1151 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153
Willy Tarreau977b8e42006-12-29 14:19:17 +01001154 if (curproxy->cap & PR_CAP_BE) {
1155 curproxy->fullconn = defproxy.fullconn;
1156 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157
Willy Tarreau977b8e42006-12-29 14:19:17 +01001158 if (defproxy.check_req)
1159 curproxy->check_req = strdup(defproxy.check_req);
1160 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161
Willy Tarreau977b8e42006-12-29 14:19:17 +01001162 if (defproxy.cookie_name)
1163 curproxy->cookie_name = strdup(defproxy.cookie_name);
1164 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001165 if (defproxy.cookie_domain)
1166 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001167
Emeric Brun647caf12009-06-30 17:57:00 +02001168 if (defproxy.rdp_cookie_name)
1169 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1170 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1171
Willy Tarreau01732802007-11-01 22:48:15 +01001172 if (defproxy.url_param_name)
1173 curproxy->url_param_name = strdup(defproxy.url_param_name);
1174 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001175
Benoitaffb4812009-03-25 13:02:10 +01001176 if (defproxy.hh_name)
1177 curproxy->hh_name = strdup(defproxy.hh_name);
1178 curproxy->hh_len = defproxy.hh_len;
1179 curproxy->hh_match_domain = defproxy.hh_match_domain;
1180
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001181 if (defproxy.iface_name)
1182 curproxy->iface_name = strdup(defproxy.iface_name);
1183 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001186 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 if (defproxy.capture_name)
1188 curproxy->capture_name = strdup(defproxy.capture_name);
1189 curproxy->capture_namelen = defproxy.capture_namelen;
1190 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192
Willy Tarreau977b8e42006-12-29 14:19:17 +01001193 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001194 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001195 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001196 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001197 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 curproxy->uri_auth = defproxy.uri_auth;
1199 curproxy->mon_net = defproxy.mon_net;
1200 curproxy->mon_mask = defproxy.mon_mask;
1201 if (defproxy.monitor_uri)
1202 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1203 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001204 if (defproxy.defbe.name)
1205 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001206 }
1207
1208 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001209 curproxy->timeout.connect = defproxy.timeout.connect;
1210 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001211 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001212 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001213 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001214 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001215 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001216 curproxy->source_addr = defproxy.source_addr;
1217 }
1218
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 curproxy->mode = defproxy.mode;
1220 curproxy->logfac1 = defproxy.logfac1;
1221 curproxy->logsrv1 = defproxy.logsrv1;
1222 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001223 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->logfac2 = defproxy.logfac2;
1225 curproxy->logsrv2 = defproxy.logsrv2;
1226 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001229 curproxy->conf.used_listener_id = EB_ROOT;
1230 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001231
Willy Tarreau93893792009-07-23 13:19:11 +02001232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1235 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001236 /* FIXME-20070101: we should do this too at the end of the
1237 * config parsing to free all default values.
1238 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001239 free(defproxy.check_req);
1240 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001241 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001242 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001243 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001244 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001245 free(defproxy.capture_name);
1246 free(defproxy.monitor_uri);
1247 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001248 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001249 free(defproxy.fwdfor_hdr_name);
1250 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001251 free(defproxy.orgto_hdr_name);
1252 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001253
Willy Tarreaua534fea2008-08-03 12:19:50 +02001254 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001255 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001256
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 /* we cannot free uri_auth because it might already be used */
1258 init_default_instance();
1259 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001260 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 }
1263 else if (curproxy == NULL) {
1264 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268
Willy Tarreau977b8e42006-12-29 14:19:17 +01001269
1270 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001272 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001273 int cur_arg;
1274
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 if (curproxy == &defproxy) {
1276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001281 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282
1283 if (strchr(args[1], ':') == NULL) {
1284 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001289
1290 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001291 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001295
Willy Tarreau90a570f2009-10-04 20:54:54 +02001296 new_listen = curproxy->listen;
1297 while (new_listen != last_listen) {
1298 new_listen->conf.file = file;
1299 new_listen->conf.line = linenum;
1300 new_listen = new_listen->next;
1301 }
1302
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001303 cur_arg = 2;
1304 while (*(args[cur_arg])) {
1305 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1306#ifdef SO_BINDTODEVICE
1307 struct listener *l;
1308
1309 if (!*args[cur_arg + 1]) {
1310 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001314 }
1315
1316 for (l = curproxy->listen; l != last_listen; l = l->next)
1317 l->interface = strdup(args[cur_arg + 1]);
1318
1319 global.last_checks |= LSTCHK_NETADM;
1320
1321 cur_arg += 2;
1322 continue;
1323#else
1324 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1325 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001328#endif
1329 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001330 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1331#ifdef TCP_MAXSEG
1332 struct listener *l;
1333 int mss;
1334
1335 if (!*args[cur_arg + 1]) {
1336 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001340 }
1341
1342 mss = str2uic(args[cur_arg + 1]);
1343 if (mss < 1 || mss > 65535) {
1344 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001348 }
1349
1350 for (l = curproxy->listen; l != last_listen; l = l->next)
1351 l->maxseg = mss;
1352
1353 cur_arg += 2;
1354 continue;
1355#else
1356 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1357 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001358 err_code |= ERR_ALERT | ERR_FATAL;
1359 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001360#endif
1361 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001362
1363 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1364#ifdef TCP_DEFER_ACCEPT
1365 struct listener *l;
1366
1367 for (l = curproxy->listen; l != last_listen; l = l->next)
1368 l->options |= LI_O_DEF_ACCEPT;
1369
1370 cur_arg ++;
1371 continue;
1372#else
1373 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1374 file, linenum, args[0], args[cur_arg]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377#endif
1378 }
1379
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001382 struct listener *l;
1383
1384 for (l = curproxy->listen; l != last_listen; l = l->next)
1385 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001386
1387 cur_arg ++;
1388 continue;
1389#else
1390 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1391 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001394#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001395 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001396
1397 if (!strcmp(args[cur_arg], "name")) {
1398 struct listener *l;
1399
1400 for (l = curproxy->listen; l != last_listen; l = l->next)
1401 l->name = strdup(args[cur_arg + 1]);
1402
1403 cur_arg += 2;
1404 continue;
1405 }
1406
1407 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001408 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001409 struct listener *l;
1410
1411 if (curproxy->listen->next != last_listen) {
1412 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1413 file, linenum, args[cur_arg]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
1416 }
1417
1418 if (!*args[cur_arg + 1]) {
1419 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1420 file, linenum, args[cur_arg]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424
1425 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001426 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001427
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001428 if (curproxy->listen->luid <= 0) {
1429 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001430 file, linenum);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433 }
1434
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001435 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1436 if (node) {
1437 l = container_of(node, struct listener, conf.id);
1438 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1439 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
1442 }
1443 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1444
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001445 cur_arg += 2;
1446 continue;
1447 }
1448
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001449 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
1457 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1458 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1459 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 /* flush useless bits */
1468 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001471 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 if (!*args[1]) {
1476 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001480 }
1481
Willy Tarreaua534fea2008-08-03 12:19:50 +02001482 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001483 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001484 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001485 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001486 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1487
Willy Tarreau93893792009-07-23 13:19:11 +02001488 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1491 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1492 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1493 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1494 else {
1495 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 }
1499 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001500 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001501 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001502
1503 if (curproxy == &defproxy) {
1504 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 }
1509
1510 if (!*args[1]) {
1511 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_ALERT | ERR_FATAL;
1514 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001515 }
1516
1517 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001518 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001519
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001520 if (curproxy->uuid <= 0) {
1521 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001525 }
1526
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001527 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1528 if (node) {
1529 struct proxy *target = container_of(node, struct proxy, conf.id);
1530 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1531 file, linenum, proxy_type_str(curproxy), curproxy->id,
1532 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
1535 }
1536 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001537 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001538 else if (!strcmp(args[0], "description")) {
1539 int i, len=0;
1540 char *d;
1541
Cyril Bonté99ed3272010-01-24 23:29:44 +01001542 if (curproxy == &defproxy) {
1543 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1544 file, linenum, args[0]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001549 if (!*args[1]) {
1550 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1551 file, linenum, args[0]);
1552 return -1;
1553 }
1554
1555 for(i=1; *args[i]; i++)
1556 len += strlen(args[i])+1;
1557
1558 d = (char *)calloc(1, len);
1559 curproxy->desc = d;
1560
1561 d += sprintf(d, "%s", args[1]);
1562 for(i=2; *args[i]; i++)
1563 d += sprintf(d, " %s", args[i]);
1564
1565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1567 curproxy->state = PR_STSTOPPED;
1568 }
1569 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1570 curproxy->state = PR_STNEW;
1571 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001572 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1573 int cur_arg = 1;
1574 unsigned int set = 0;
1575
1576 while (*args[cur_arg]) {
1577 int u;
1578 if (strcmp(args[cur_arg], "all") == 0) {
1579 set = 0;
1580 break;
1581 }
1582 else if (strcmp(args[cur_arg], "odd") == 0) {
1583 set |= 0x55555555;
1584 }
1585 else if (strcmp(args[cur_arg], "even") == 0) {
1586 set |= 0xAAAAAAAA;
1587 }
1588 else {
1589 u = str2uic(args[cur_arg]);
1590 if (u < 1 || u > 32) {
1591 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001595 }
1596 if (u > global.nbproc) {
1597 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001600 }
1601 set |= 1 << (u - 1);
1602 }
1603 cur_arg++;
1604 }
1605 curproxy->bind_proc = set;
1606 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001612 }
1613
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001614 err = invalid_char(args[1]);
1615 if (err) {
1616 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1617 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001619 }
1620
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001621 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1622 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1623 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001626 }
1627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1629 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (*(args[1]) == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001640
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001641 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001642 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 curproxy->cookie_name = strdup(args[1]);
1644 curproxy->cookie_len = strlen(curproxy->cookie_name);
1645
1646 cur_arg = 2;
1647 while (*(args[cur_arg])) {
1648 if (!strcmp(args[cur_arg], "rewrite")) {
1649 curproxy->options |= PR_O_COOK_RW;
1650 }
1651 else if (!strcmp(args[cur_arg], "indirect")) {
1652 curproxy->options |= PR_O_COOK_IND;
1653 }
1654 else if (!strcmp(args[cur_arg], "insert")) {
1655 curproxy->options |= PR_O_COOK_INS;
1656 }
1657 else if (!strcmp(args[cur_arg], "nocache")) {
1658 curproxy->options |= PR_O_COOK_NOC;
1659 }
1660 else if (!strcmp(args[cur_arg], "postonly")) {
1661 curproxy->options |= PR_O_COOK_POST;
1662 }
1663 else if (!strcmp(args[cur_arg], "prefix")) {
1664 curproxy->options |= PR_O_COOK_PFX;
1665 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001666 else if (!strcmp(args[cur_arg], "domain")) {
1667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1669 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001672 }
1673
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001674 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001676 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1677 " dots nor does not start with a dot."
1678 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001679 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001680 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001681 }
1682
1683 err = invalid_domainchar(args[cur_arg + 1]);
1684 if (err) {
1685 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1686 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001689 }
1690
Willy Tarreau68a897b2009-12-03 23:28:34 +01001691 if (!curproxy->cookie_domain) {
1692 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1693 } else {
1694 /* one domain was already specified, add another one by
1695 * building the string which will be returned along with
1696 * the cookie.
1697 */
1698 char *new_ptr;
1699 int new_len = strlen(curproxy->cookie_domain) +
1700 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1701 new_ptr = malloc(new_len);
1702 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1703 free(curproxy->cookie_domain);
1704 curproxy->cookie_domain = new_ptr;
1705 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001706 cur_arg++;
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 }
1714 cur_arg++;
1715 }
1716 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1717 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1718 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001719 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 }
1721
1722 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1723 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1724 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 }
1727 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001728 else if (!strcmp(args[0], "persist")) { /* persist */
1729 if (*(args[1]) == 0) {
1730 Alert("parsing [%s:%d] : missing persist method.\n",
1731 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001734 }
1735
1736 if (!strncmp(args[1], "rdp-cookie", 10)) {
1737 curproxy->options2 |= PR_O2_RDPC_PRST;
1738
Emeric Brunb982a3d2010-01-04 15:45:53 +01001739 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001740 const char *beg, *end;
1741
1742 beg = args[1] + 11;
1743 end = strchr(beg, ')');
1744
1745 if (!end || end == beg) {
1746 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001750 }
1751
1752 free(curproxy->rdp_cookie_name);
1753 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1754 curproxy->rdp_cookie_len = end-beg;
1755 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001756 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001757 free(curproxy->rdp_cookie_name);
1758 curproxy->rdp_cookie_name = strdup("msts");
1759 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1760 }
1761 else { /* syntax */
1762 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1763 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001766 }
1767 }
1768 else {
1769 Alert("parsing [%s:%d] : unknown persist method.\n",
1770 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001773 }
1774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001776 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001778 if (curproxy == &defproxy) {
1779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau977b8e42006-12-29 14:19:17 +01001784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001788 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 }
1793 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001794 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 curproxy->appsession_name = strdup(args[1]);
1796 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1797 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001798 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1799 if (err) {
1800 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1801 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001804 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001805 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001806
Willy Tarreau51041c72007-09-09 21:56:53 +02001807 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1808 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_ALERT | ERR_ABORT;
1810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001812
1813 cur_arg = 6;
1814 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001815 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1816 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001817 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001818 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001819 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001820 } else if (!strcmp(args[cur_arg], "prefix")) {
1821 curproxy->options2 |= PR_O2_AS_PFX;
1822 } else if (!strcmp(args[cur_arg], "mode")) {
1823 if (!*args[cur_arg + 1]) {
1824 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1825 file, linenum, args[0], args[cur_arg]);
1826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829
1830 cur_arg++;
1831 if (!strcmp(args[cur_arg], "query-string")) {
1832 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1833 curproxy->options2 |= PR_O2_AS_M_QS;
1834 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1836 curproxy->options2 |= PR_O2_AS_M_PP;
1837 } else {
1838 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001843 cur_arg++;
1844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 } /* Url App Session */
1846 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001851 if (curproxy == &defproxy) {
1852 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if (*(args[4]) == 0) {
1858 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001863 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->capture_name = strdup(args[2]);
1865 curproxy->capture_namelen = strlen(curproxy->capture_name);
1866 curproxy->capture_len = atol(args[4]);
1867 if (curproxy->capture_len >= CAPTURE_LEN) {
1868 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1869 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->capture_len = CAPTURE_LEN - 1;
1872 }
1873 curproxy->to_log |= LW_COOKIE;
1874 }
1875 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1876 struct cap_hdr *hdr;
1877
1878 if (curproxy == &defproxy) {
1879 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 }
1883
1884 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1885 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1886 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
1890
1891 hdr = calloc(sizeof(struct cap_hdr), 1);
1892 hdr->next = curproxy->req_cap;
1893 hdr->name = strdup(args[3]);
1894 hdr->namelen = strlen(args[3]);
1895 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001896 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 hdr->index = curproxy->nb_req_cap++;
1898 curproxy->req_cap = hdr;
1899 curproxy->to_log |= LW_REQHDR;
1900 }
1901 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1902 struct cap_hdr *hdr;
1903
1904 if (curproxy == &defproxy) {
1905 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909
1910 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1911 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1912 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
1916 hdr = calloc(sizeof(struct cap_hdr), 1);
1917 hdr->next = curproxy->rsp_cap;
1918 hdr->name = strdup(args[3]);
1919 hdr->namelen = strlen(args[3]);
1920 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001921 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 hdr->index = curproxy->nb_rsp_cap++;
1923 curproxy->rsp_cap = hdr;
1924 curproxy->to_log |= LW_RSPHDR;
1925 }
1926 else {
1927 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 if (*(args[1]) == 0) {
1938 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
1943 curproxy->conn_retries = atol(args[1]);
1944 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001945 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1946 struct req_acl_rule *req_acl;
1947
1948 if (curproxy == &defproxy) {
1949 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
1952 }
1953
1954
1955 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1956 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1957 file, linenum, args[0]);
1958 err_code |= ERR_WARN;
1959 }
1960
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001961 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001962
1963 if (!req_acl) {
1964 err_code |= ERR_ALERT | ERR_ABORT;
1965 goto out;
1966 }
1967
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001968 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001969 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1970 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001971 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001972 if (curproxy == &defproxy) {
1973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001976 }
1977
Willy Tarreauef6494c2010-01-28 17:12:36 +01001978 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001979 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1980 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001983 }
1984
Willy Tarreauef6494c2010-01-28 17:12:36 +01001985 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001986 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001990 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001991
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001992 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001993 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001994 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001995 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 struct redirect_rule *rule;
1997 int cur_arg;
1998 int type = REDIRECT_TYPE_NONE;
1999 int code = 302;
2000 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002001 char *cookie = NULL;
2002 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002003 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002004
Cyril Bonté99ed3272010-01-24 23:29:44 +01002005 if (curproxy == &defproxy) {
2006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002011 cur_arg = 1;
2012 while (*(args[cur_arg])) {
2013 if (!strcmp(args[cur_arg], "location")) {
2014 if (!*args[cur_arg + 1]) {
2015 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2016 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002019 }
2020
2021 type = REDIRECT_TYPE_LOCATION;
2022 cur_arg++;
2023 destination = args[cur_arg];
2024 }
2025 else if (!strcmp(args[cur_arg], "prefix")) {
2026 if (!*args[cur_arg + 1]) {
2027 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2028 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002031 }
2032
2033 type = REDIRECT_TYPE_PREFIX;
2034 cur_arg++;
2035 destination = args[cur_arg];
2036 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002037 else if (!strcmp(args[cur_arg], "set-cookie")) {
2038 if (!*args[cur_arg + 1]) {
2039 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2040 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002043 }
2044
2045 cur_arg++;
2046 cookie = args[cur_arg];
2047 cookie_set = 1;
2048 }
2049 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2050 if (!*args[cur_arg + 1]) {
2051 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2052 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002055 }
2056
2057 cur_arg++;
2058 cookie = args[cur_arg];
2059 cookie_set = 0;
2060 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002061 else if (!strcmp(args[cur_arg],"code")) {
2062 if (!*args[cur_arg + 1]) {
2063 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002067 }
2068 cur_arg++;
2069 code = atol(args[cur_arg]);
2070 if (code < 301 || code > 303) {
2071 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2072 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002075 }
2076 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002077 else if (!strcmp(args[cur_arg],"drop-query")) {
2078 flags |= REDIRECT_FLAG_DROP_QS;
2079 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002080 else if (!strcmp(args[cur_arg],"append-slash")) {
2081 flags |= REDIRECT_FLAG_APPEND_SLASH;
2082 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002083 else if (strcmp(args[cur_arg], "if") == 0 ||
2084 strcmp(args[cur_arg], "unless") == 0) {
2085 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2086 if (!cond) {
2087 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2088 file, linenum, args[0]);
2089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002092 break;
2093 }
2094 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002095 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002096 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002099 }
2100 cur_arg++;
2101 }
2102
2103 if (type == REDIRECT_TYPE_NONE) {
2104 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002108 }
2109
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002110 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2111 rule->cond = cond;
2112 rule->rdr_str = strdup(destination);
2113 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002114 if (cookie) {
2115 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002116 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002117 */
2118 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002119 if (cookie_set) {
2120 rule->cookie_str = malloc(rule->cookie_len + 10);
2121 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2122 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2123 rule->cookie_len += 9;
2124 } else {
2125 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002126 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002127 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2128 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002129 }
2130 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002131 rule->type = type;
2132 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002133 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002134 LIST_INIT(&rule->list);
2135 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002136 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002137 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002138 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002139 struct switching_rule *rule;
2140
Willy Tarreaub099aca2008-10-12 17:26:37 +02002141 if (curproxy == &defproxy) {
2142 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002145 }
2146
Willy Tarreau55ea7572007-06-17 19:56:27 +02002147 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002149
2150 if (*(args[1]) == 0) {
2151 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002154 }
2155
Willy Tarreauef6494c2010-01-28 17:12:36 +01002156 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002157 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002161 }
2162
Willy Tarreauef6494c2010-01-28 17:12:36 +01002163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002164 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002168 }
2169
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002170 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002171
Willy Tarreau55ea7572007-06-17 19:56:27 +02002172 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2173 rule->cond = cond;
2174 rule->be.name = strdup(args[1]);
2175 LIST_INIT(&rule->list);
2176 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2177 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002178 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002179 struct force_persist_rule *rule;
2180
2181 if (curproxy == &defproxy) {
2182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186
2187 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2188 err_code |= ERR_WARN;
2189
Willy Tarreauef6494c2010-01-28 17:12:36 +01002190 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002191 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2192 file, linenum, args[0]);
2193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
2195 }
2196
Willy Tarreauef6494c2010-01-28 17:12:36 +01002197 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002198 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2199 file, linenum);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002204 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002205
2206 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2207 rule->cond = cond;
2208 LIST_INIT(&rule->list);
2209 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2210 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002211 else if (!strcmp(args[0], "stick-table")) {
2212 int myidx = 1;
2213
2214 curproxy->table.type = (unsigned int)-1;
2215 while (*args[myidx]) {
2216 const char *err;
2217
2218 if (strcmp(args[myidx], "size") == 0) {
2219 myidx++;
2220 if (!*(args[myidx])) {
2221 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2222 file, linenum, args[myidx-1]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2227 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2228 file, linenum, *err, args[myidx-1]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002233 }
2234 else if (strcmp(args[myidx], "expire") == 0) {
2235 myidx++;
2236 if (!*(args[myidx])) {
2237 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2238 file, linenum, args[myidx-1]);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2243 if (err) {
2244 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2245 file, linenum, *err, args[myidx-1]);
2246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
2248 }
2249 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002250 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002251 }
2252 else if (strcmp(args[myidx], "nopurge") == 0) {
2253 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002254 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002255 }
2256 else if (strcmp(args[myidx], "type") == 0) {
2257 myidx++;
2258 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2259 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2260 file, linenum, args[myidx]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002264 /* myidx already points to next arg */
2265 }
2266 else {
2267 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2268 file, linenum, args[myidx]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002271 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002272 }
2273
2274 if (!curproxy->table.size) {
2275 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2276 file, linenum);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
2281 if (curproxy->table.type == (unsigned int)-1) {
2282 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2283 file, linenum);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287 }
2288 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002289 struct sticking_rule *rule;
2290 struct pattern_expr *expr;
2291 int myidx = 0;
2292 const char *name = NULL;
2293 int flags;
2294
2295 if (curproxy == &defproxy) {
2296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
2299 }
2300
2301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2302 err_code |= ERR_WARN;
2303 goto out;
2304 }
2305
2306 myidx++;
2307 if ((strcmp(args[myidx], "store") == 0) ||
2308 (strcmp(args[myidx], "store-request") == 0)) {
2309 myidx++;
2310 flags = STK_IS_STORE;
2311 }
2312 else if (strcmp(args[myidx], "store-response") == 0) {
2313 myidx++;
2314 flags = STK_IS_STORE | STK_ON_RSP;
2315 }
2316 else if (strcmp(args[myidx], "match") == 0) {
2317 myidx++;
2318 flags = STK_IS_MATCH;
2319 }
2320 else if (strcmp(args[myidx], "on") == 0) {
2321 myidx++;
2322 flags = STK_IS_MATCH | STK_IS_STORE;
2323 }
2324 else {
2325 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
2330 if (*(args[myidx]) == 0) {
2331 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
2336 expr = pattern_parse_expr(args, &myidx);
2337 if (!expr) {
2338 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342
2343 if (flags & STK_ON_RSP) {
2344 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2345 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2346 file, linenum, args[0], expr->fetch->kw);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 } else {
2351 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2352 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2353 file, linenum, args[0], expr->fetch->kw);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357 }
2358
2359 if (strcmp(args[myidx], "table") == 0) {
2360 myidx++;
2361 name = args[myidx++];
2362 }
2363
Willy Tarreauef6494c2010-01-28 17:12:36 +01002364 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2365 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002366 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2367 file, linenum, args[0]);
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002371 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002372 else if (*(args[myidx])) {
2373 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2374 file, linenum, args[0], args[myidx]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002379 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2380
Emeric Brunb982a3d2010-01-04 15:45:53 +01002381 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2382 rule->cond = cond;
2383 rule->expr = expr;
2384 rule->flags = flags;
2385 rule->table.name = name ? strdup(name) : NULL;
2386 LIST_INIT(&rule->list);
2387 if (flags & STK_ON_RSP)
2388 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2389 else
2390 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002395
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2397 curproxy->uri_auth = NULL; /* we must detach from the default config */
2398
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002399 if (!*args[1]) {
2400 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 } else if (!strcmp(args[1], "uri")) {
2402 if (*(args[2]) == 0) {
2403 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411 } else if (!strcmp(args[1], "realm")) {
2412 if (*(args[2]) == 0) {
2413 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2417 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_ABORT;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002421 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002422 unsigned interval;
2423
2424 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2425 if (err) {
2426 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2427 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002430 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_ABORT;
2433 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002434 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002435 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2436 struct req_acl_rule *req_acl;
2437
2438 if (curproxy == &defproxy) {
2439 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
2444 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2445 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2446 err_code |= ERR_ALERT | ERR_ABORT;
2447 goto out;
2448 }
2449
2450 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2451 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2452 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2453 file, linenum, args[0]);
2454 err_code |= ERR_WARN;
2455 }
2456
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002457 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002458
2459 if (!req_acl) {
2460 err_code |= ERR_ALERT | ERR_ABORT;
2461 goto out;
2462 }
2463
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002464 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002465 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 } else if (!strcmp(args[1], "auth")) {
2468 if (*(args[2]) == 0) {
2469 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2473 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_ABORT;
2475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
2477 } else if (!strcmp(args[1], "scope")) {
2478 if (*(args[2]) == 0) {
2479 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2483 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_ABORT;
2485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }
2487 } else if (!strcmp(args[1], "enable")) {
2488 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2489 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_ABORT;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002493 } else if (!strcmp(args[1], "hide-version")) {
2494 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_ABORT;
2497 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002498 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002499 } else if (!strcmp(args[1], "show-legends")) {
2500 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2501 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2502 err_code |= ERR_ALERT | ERR_ABORT;
2503 goto out;
2504 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002505 } else if (!strcmp(args[1], "show-node")) {
2506
2507 if (*args[2]) {
2508 int i;
2509 char c;
2510
2511 for (i=0; args[2][i]; i++) {
2512 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002513 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2514 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002515 break;
2516 }
2517
2518 if (!i || args[2][i]) {
2519 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2520 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2521 file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 }
2526
2527 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2528 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2529 err_code |= ERR_ALERT | ERR_ABORT;
2530 goto out;
2531 }
2532 } else if (!strcmp(args[1], "show-desc")) {
2533 char *desc = NULL;
2534
2535 if (*args[2]) {
2536 int i, len=0;
2537 char *d;
2538
2539 for(i=2; *args[i]; i++)
2540 len += strlen(args[i])+1;
2541
2542 desc = d = (char *)calloc(1, len);
2543
2544 d += sprintf(d, "%s", args[2]);
2545 for(i=3; *args[i]; i++)
2546 d += sprintf(d, " %s", args[i]);
2547 }
2548
2549 if (!*args[2] && !global.desc)
2550 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2551 file, linenum, args[1]);
2552 else {
2553 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2554 free(desc);
2555 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2556 err_code |= ERR_ALERT | ERR_ABORT;
2557 goto out;
2558 }
2559 free(desc);
2560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002562stats_error_parsing:
2563 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2564 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
2568 }
2569 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002570 int optnum;
2571
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002572 if (*(args[1]) == '\0') {
2573 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002578
2579 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2580 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002581 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2582 err_code |= ERR_WARN;
2583 goto out;
2584 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002585
Willy Tarreau3842f002009-06-14 11:39:52 +02002586 curproxy->no_options &= ~cfg_opts[optnum].val;
2587 curproxy->options &= ~cfg_opts[optnum].val;
2588
2589 switch (kwm) {
2590 case KWM_STD:
2591 curproxy->options |= cfg_opts[optnum].val;
2592 break;
2593 case KWM_NO:
2594 curproxy->no_options |= cfg_opts[optnum].val;
2595 break;
2596 case KWM_DEF: /* already cleared */
2597 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002598 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002599
Willy Tarreau93893792009-07-23 13:19:11 +02002600 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002601 }
2602 }
2603
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002604 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2605 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002606 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2607 err_code |= ERR_WARN;
2608 goto out;
2609 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002610
Willy Tarreau3842f002009-06-14 11:39:52 +02002611 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2612 curproxy->options2 &= ~cfg_opts2[optnum].val;
2613
2614 switch (kwm) {
2615 case KWM_STD:
2616 curproxy->options2 |= cfg_opts2[optnum].val;
2617 break;
2618 case KWM_NO:
2619 curproxy->no_options2 |= cfg_opts2[optnum].val;
2620 break;
2621 case KWM_DEF: /* already cleared */
2622 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002623 }
Willy Tarreau93893792009-07-23 13:19:11 +02002624 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002625 }
2626 }
2627
Willy Tarreau3842f002009-06-14 11:39:52 +02002628 if (kwm != KWM_STD) {
2629 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002630 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002633 }
2634
Emeric Brun3a058f32009-06-30 18:26:00 +02002635 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002637 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002639 if (*(args[2]) != '\0') {
2640 if (!strcmp(args[2], "clf")) {
2641 curproxy->options2 |= PR_O2_CLFLOG;
2642 } else {
2643 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002646 }
2647 }
2648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else if (!strcmp(args[1], "tcplog"))
2650 /* generate a detailed TCP log */
2651 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 else if (!strcmp(args[1], "tcpka")) {
2653 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002654 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002656
2657 if (curproxy->cap & PR_CAP_FE)
2658 curproxy->options |= PR_O_TCP_CLI_KA;
2659 if (curproxy->cap & PR_CAP_BE)
2660 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 }
2662 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002663 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_WARN;
2665
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002667 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002668 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002669 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002670 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002671 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002672 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 if (!*args[2]) { /* no argument */
2674 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2675 curproxy->check_len = strlen(DEF_CHECK_REQ);
2676 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002677 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 curproxy->check_req = (char *)malloc(reqlen);
2679 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002680 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002682 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 if (*args[4])
2684 reqlen += strlen(args[4]);
2685 else
2686 reqlen += strlen("HTTP/1.0");
2687
2688 curproxy->check_req = (char *)malloc(reqlen);
2689 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002690 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002692 }
2693 else if (!strcmp(args[1], "ssl-hello-chk")) {
2694 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002695 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002697
Willy Tarreaua534fea2008-08-03 12:19:50 +02002698 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002699 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002700 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002701 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002702 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002703 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 }
Willy Tarreau23677902007-05-08 23:50:35 +02002705 else if (!strcmp(args[1], "smtpchk")) {
2706 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002707 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002708 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002709 curproxy->options &= ~PR_O_HTTP_CHK;
2710 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002711 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002712 curproxy->options |= PR_O_SMTP_CHK;
2713
2714 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2715 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2716 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2717 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2718 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2719 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2720 curproxy->check_req = (char *)malloc(reqlen);
2721 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2722 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2723 } else {
2724 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2725 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2726 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2727 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2728 }
2729 }
2730 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002731 else if (!strcmp(args[1], "mysql-check")) {
2732 /* use MYSQL request to check servers' health */
2733 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002734 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002735 curproxy->options &= ~PR_O_HTTP_CHK;
2736 curproxy->options &= ~PR_O_SSL3_CHK;
2737 curproxy->options &= ~PR_O_SMTP_CHK;
2738 curproxy->options2 |= PR_O2_MYSQL_CHK;
2739 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002740 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002741 int cur_arg;
2742
2743 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2744 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002745 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002746
2747 curproxy->options |= PR_O_FWDFOR;
2748
2749 free(curproxy->fwdfor_hdr_name);
2750 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2751 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2752
2753 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2754 cur_arg = 2;
2755 while (*(args[cur_arg])) {
2756 if (!strcmp(args[cur_arg], "except")) {
2757 /* suboption except - needs additional argument for it */
2758 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2759 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2760 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002763 }
2764 /* flush useless bits */
2765 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002766 cur_arg += 2;
2767 } else if (!strcmp(args[cur_arg], "header")) {
2768 /* suboption header - needs additional argument for it */
2769 if (*(args[cur_arg+1]) == 0) {
2770 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2771 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002774 }
2775 free(curproxy->fwdfor_hdr_name);
2776 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2777 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2778 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002779 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002780 /* unknown suboption - catchall */
2781 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2782 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002785 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002786 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002787 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002788 else if (!strcmp(args[1], "originalto")) {
2789 int cur_arg;
2790
2791 /* insert x-original-to field, but not for the IP address listed as an except.
2792 * set default options (ie: bitfield, header name, etc)
2793 */
2794
2795 curproxy->options |= PR_O_ORGTO;
2796
2797 free(curproxy->orgto_hdr_name);
2798 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2799 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2800
2801 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2802 cur_arg = 2;
2803 while (*(args[cur_arg])) {
2804 if (!strcmp(args[cur_arg], "except")) {
2805 /* suboption except - needs additional argument for it */
2806 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2807 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2808 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002811 }
2812 /* flush useless bits */
2813 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2814 cur_arg += 2;
2815 } else if (!strcmp(args[cur_arg], "header")) {
2816 /* suboption header - needs additional argument for it */
2817 if (*(args[cur_arg+1]) == 0) {
2818 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2819 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002822 }
2823 free(curproxy->orgto_hdr_name);
2824 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2825 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2826 cur_arg += 2;
2827 } else {
2828 /* unknown suboption - catchall */
2829 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2830 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002833 }
2834 } /* end while loop */
2835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 else {
2837 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
Willy Tarreau93893792009-07-23 13:19:11 +02002841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002843 else if (!strcmp(args[0], "default_backend")) {
2844 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002846
2847 if (*(args[1]) == 0) {
2848 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002851 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002852 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002853 curproxy->defbe.name = strdup(args[1]);
2854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002858
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002859 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2860 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 /* enable reconnections to dispatch */
2863 curproxy->options |= PR_O_REDISP;
2864 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002865 else if (!strcmp(args[0], "http-check")) {
2866 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002867 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002868
2869 if (strcmp(args[1], "disable-on-404") == 0) {
2870 /* enable a graceful server shutdown on an HTTP 404 response */
2871 curproxy->options |= PR_O_DISABLE404;
2872 }
Willy Tarreauef781042010-01-27 11:53:01 +01002873 else if (strcmp(args[1], "send-state") == 0) {
2874 /* enable emission of the apparent state of a server in HTTP checks */
2875 curproxy->options2 |= PR_O2_CHK_SNDST;
2876 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002877 else {
2878 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002881 }
2882 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002883 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002884 if (curproxy == &defproxy) {
2885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002888 }
2889
Willy Tarreaub80c2302007-11-30 20:51:32 +01002890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002892
2893 if (strcmp(args[1], "fail") == 0) {
2894 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002895 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002896 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2897 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002900 }
2901
Willy Tarreauef6494c2010-01-28 17:12:36 +01002902 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002903 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2904 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002907 }
2908 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2909 }
2910 else {
2911 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002914 }
2915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916#ifdef TPROXY
2917 else if (!strcmp(args[0], "transparent")) {
2918 /* enable transparent proxy connections */
2919 curproxy->options |= PR_O_TRANSP;
2920 }
2921#endif
2922 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 }
2931 curproxy->maxconn = atol(args[1]);
2932 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002933 else if (!strcmp(args[0], "backlog")) { /* backlog */
2934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002936
2937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002941 }
2942 curproxy->backlog = atol(args[1]);
2943 }
Willy Tarreau86034312006-12-29 00:10:33 +01002944 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002947
Willy Tarreau86034312006-12-29 00:10:33 +01002948 if (*(args[1]) == 0) {
2949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002952 }
2953 curproxy->fullconn = atol(args[1]);
2954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2956 if (*(args[1]) == 0) {
2957 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002961 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2962 if (err) {
2963 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2964 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002967 }
2968 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
2970 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002971 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 if (curproxy == &defproxy) {
2973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002977 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 if (strchr(args[1], ':') == NULL) {
2981 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002985 sk = str2sa(args[1]);
2986 if (!sk) {
2987 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002996
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002997 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002998 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2999 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003004 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3006 err_code |= ERR_WARN;
3007
3008 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3009 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3010 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3011 }
3012 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3013 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3014 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3015 }
3016 else {
3017 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003022 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003024 char *rport, *raddr;
3025 short realport = 0;
3026 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003028 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003033 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035
3036 if (!*args[2]) {
3037 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003042
3043 err = invalid_char(args[1]);
3044 if (err) {
3045 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3046 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003049 }
3050
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003051 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003052 struct sockaddr_in *sk;
3053
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003054 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3055 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3056 err_code |= ERR_ALERT | ERR_ABORT;
3057 goto out;
3058 }
3059
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003060 /* the servers are linked backwards first */
3061 newsrv->next = curproxy->srv;
3062 curproxy->srv = newsrv;
3063 newsrv->proxy = curproxy;
3064 newsrv->conf.file = file;
3065 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003067 LIST_INIT(&newsrv->pendconns);
3068 do_check = 0;
3069 newsrv->state = SRV_RUNNING; /* early server setup */
3070 newsrv->last_change = now.tv_sec;
3071 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003073 /* several ways to check the port component :
3074 * - IP => port=+0, relative
3075 * - IP: => port=+0, relative
3076 * - IP:N => port=N, absolute
3077 * - IP:+N => port=+N, relative
3078 * - IP:-N => port=-N, relative
3079 */
3080 raddr = strdup(args[2]);
3081 rport = strchr(raddr, ':');
3082 if (rport) {
3083 *rport++ = 0;
3084 realport = atol(rport);
3085 if (!isdigit((unsigned char)*rport))
3086 newsrv->state |= SRV_MAPPORTS;
3087 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003089
Willy Tarreaud5191e72010-02-09 20:50:45 +01003090 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003091 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003092 if (!sk) {
3093 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097 newsrv->addr = *sk;
3098 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003099
3100 newsrv->check_port = curproxy->defsrv.check_port;
3101 newsrv->inter = curproxy->defsrv.inter;
3102 newsrv->fastinter = curproxy->defsrv.fastinter;
3103 newsrv->downinter = curproxy->defsrv.downinter;
3104 newsrv->rise = curproxy->defsrv.rise;
3105 newsrv->fall = curproxy->defsrv.fall;
3106 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3107 newsrv->minconn = curproxy->defsrv.minconn;
3108 newsrv->maxconn = curproxy->defsrv.maxconn;
3109 newsrv->slowstart = curproxy->defsrv.slowstart;
3110 newsrv->onerror = curproxy->defsrv.onerror;
3111 newsrv->consecutive_errors_limit
3112 = curproxy->defsrv.consecutive_errors_limit;
3113 newsrv->uweight = newsrv->iweight
3114 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003116 newsrv->curfd = -1; /* no health-check in progress */
3117 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003119 cur_arg = 3;
3120 } else {
3121 newsrv = &curproxy->defsrv;
3122 cur_arg = 1;
3123 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003124
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003126 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003127 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003128
3129 if (!*args[cur_arg + 1]) {
3130 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3131 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003134 }
3135
3136 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003137 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003138
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003139 if (newsrv->puid <= 0) {
3140 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003141 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003144 }
3145
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003146 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3147 if (node) {
3148 struct server *target = container_of(node, struct server, conf.id);
3149 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3150 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003155 cur_arg += 2;
3156 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003157 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 newsrv->cookie = strdup(args[cur_arg + 1]);
3159 newsrv->cklen = strlen(args[cur_arg + 1]);
3160 cur_arg += 2;
3161 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003162 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003163 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3164 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3165 cur_arg += 2;
3166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003168 if (!*args[cur_arg + 1]) {
3169 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3170 file, linenum, args[cur_arg]);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
3173 }
3174
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003176 if (newsrv->rise <= 0) {
3177 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3178 file, linenum, args[cur_arg]);
3179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
3181 }
3182
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 newsrv->health = newsrv->rise;
3184 cur_arg += 2;
3185 }
3186 else if (!strcmp(args[cur_arg], "fall")) {
3187 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003188
3189 if (!*args[cur_arg + 1]) {
3190 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3191 file, linenum, args[cur_arg]);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
3195
3196 if (newsrv->fall <= 0) {
3197 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3198 file, linenum, args[cur_arg]);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 cur_arg += 2;
3204 }
3205 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003206 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3207 if (err) {
3208 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3209 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003212 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003213 if (val <= 0) {
3214 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3215 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003218 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003219 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 cur_arg += 2;
3221 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003222 else if (!strcmp(args[cur_arg], "fastinter")) {
3223 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3224 if (err) {
3225 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3226 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003229 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003230 if (val <= 0) {
3231 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3232 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003235 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003236 newsrv->fastinter = val;
3237 cur_arg += 2;
3238 }
3239 else if (!strcmp(args[cur_arg], "downinter")) {
3240 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3241 if (err) {
3242 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3243 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003246 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003247 if (val <= 0) {
3248 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3249 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003252 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003253 newsrv->downinter = val;
3254 cur_arg += 2;
3255 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003256 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003257 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3258 if (!sk) {
3259 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
3262 }
3263 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003264 cur_arg += 2;
3265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 else if (!strcmp(args[cur_arg], "port")) {
3267 newsrv->check_port = atol(args[cur_arg + 1]);
3268 cur_arg += 2;
3269 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003270 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 newsrv->state |= SRV_BACKUP;
3272 cur_arg ++;
3273 }
3274 else if (!strcmp(args[cur_arg], "weight")) {
3275 int w;
3276 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003277 if (w < 0 || w > 256) {
3278 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003283 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 cur_arg += 2;
3285 }
3286 else if (!strcmp(args[cur_arg], "minconn")) {
3287 newsrv->minconn = atol(args[cur_arg + 1]);
3288 cur_arg += 2;
3289 }
3290 else if (!strcmp(args[cur_arg], "maxconn")) {
3291 newsrv->maxconn = atol(args[cur_arg + 1]);
3292 cur_arg += 2;
3293 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003294 else if (!strcmp(args[cur_arg], "maxqueue")) {
3295 newsrv->maxqueue = atol(args[cur_arg + 1]);
3296 cur_arg += 2;
3297 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003298 else if (!strcmp(args[cur_arg], "slowstart")) {
3299 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003300 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003301 if (err) {
3302 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3303 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003306 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003307 if (val <= 0) {
3308 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3309 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003312 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003313 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003314 cur_arg += 2;
3315 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003316 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003317
3318 if (!*args[cur_arg + 1]) {
3319 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3320 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003323 }
3324
3325 newsrv->trackit = strdup(args[cur_arg + 1]);
3326
3327 cur_arg += 2;
3328 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003329 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 global.maxsock++;
3331 do_check = 1;
3332 cur_arg += 1;
3333 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003334 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003335 if (!strcmp(args[cur_arg + 1], "none"))
3336 newsrv->observe = HANA_OBS_NONE;
3337 else if (!strcmp(args[cur_arg + 1], "layer4"))
3338 newsrv->observe = HANA_OBS_LAYER4;
3339 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3340 if (curproxy->mode != PR_MODE_HTTP) {
3341 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3342 file, linenum, args[cur_arg + 1]);
3343 err_code |= ERR_ALERT;
3344 }
3345 newsrv->observe = HANA_OBS_LAYER7;
3346 }
3347 else {
3348 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3349 "'l4events', 'http-responses' but get '%s'\n",
3350 file, linenum, args[cur_arg], args[cur_arg + 1]);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
3353 }
3354
3355 cur_arg += 2;
3356 }
3357 else if (!strcmp(args[cur_arg], "on-error")) {
3358 if (!strcmp(args[cur_arg + 1], "fastinter"))
3359 newsrv->onerror = HANA_ONERR_FASTINTER;
3360 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3361 newsrv->onerror = HANA_ONERR_FAILCHK;
3362 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3363 newsrv->onerror = HANA_ONERR_SUDDTH;
3364 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3365 newsrv->onerror = HANA_ONERR_MARKDWN;
3366 else {
3367 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3368 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3369 file, linenum, args[cur_arg], args[cur_arg + 1]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
3373
3374 cur_arg += 2;
3375 }
3376 else if (!strcmp(args[cur_arg], "error-limit")) {
3377 if (!*args[cur_arg + 1]) {
3378 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3379 file, linenum, args[cur_arg]);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383
3384 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3385
3386 if (newsrv->consecutive_errors_limit <= 0) {
3387 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3388 file, linenum, args[cur_arg]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003392 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003393 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003394 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003395 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003396 struct sockaddr_in *sk;
3397
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003399#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003400 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003401 file, linenum, "source", "usesrc");
3402#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003403 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003405#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
3409 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003410 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3411 if (!sk) {
3412 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
3415 }
3416 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003417
3418 if (port_low != port_high) {
3419 int i;
3420 if (port_low <= 0 || port_low > 65535 ||
3421 port_high <= 0 || port_high > 65535 ||
3422 port_low > port_high) {
3423 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3424 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003427 }
3428 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3429 for (i = 0; i < newsrv->sport_range->size; i++)
3430 newsrv->sport_range->ports[i] = port_low + i;
3431 }
3432
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003434 while (*(args[cur_arg])) {
3435 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003436#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3437#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003438 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3439 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3440 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003443 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003444#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003445 if (!*args[cur_arg + 1]) {
3446 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3447 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003450 }
3451 if (!strcmp(args[cur_arg + 1], "client")) {
3452 newsrv->state |= SRV_TPROXY_CLI;
3453 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3454 newsrv->state |= SRV_TPROXY_CIP;
3455 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003456 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3457 if (!sk) {
3458 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003463 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003464 }
3465 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003466#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003467 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003468#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003469 cur_arg += 2;
3470 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003471#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003472 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003473 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003476#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3477 } /* "usesrc" */
3478
3479 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3480#ifdef SO_BINDTODEVICE
3481 if (!*args[cur_arg + 1]) {
3482 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003486 }
3487 if (newsrv->iface_name)
3488 free(newsrv->iface_name);
3489
3490 newsrv->iface_name = strdup(args[cur_arg + 1]);
3491 newsrv->iface_len = strlen(newsrv->iface_name);
3492 global.last_checks |= LSTCHK_NETADM;
3493#else
3494 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3495 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003498#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003499 cur_arg += 2;
3500 continue;
3501 }
3502 /* this keyword in not an option of "source" */
3503 break;
3504 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003506 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003507 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3508 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003513 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003514 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 +01003515 file, linenum, newsrv->id);
3516 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003517 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 +01003518 file, linenum);
3519
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
3523 }
3524
3525 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003526 if (newsrv->trackit) {
3527 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003531 }
3532
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003533 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3534 newsrv->check_port = newsrv->check_addr.sin_port;
3535
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3537 newsrv->check_port = realport; /* by default */
3538 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003539 /* not yet valid, because no port was set on
3540 * the server either. We'll check if we have
3541 * a known port on the first listener.
3542 */
3543 struct listener *l;
3544 l = curproxy->listen;
3545 if (l) {
3546 int port;
3547 port = (l->addr.ss_family == AF_INET6)
3548 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3549 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3550 newsrv->check_port = port;
3551 }
3552 }
3553 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3555 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003559
3560 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 newsrv->state |= SRV_CHECKED;
3562 }
3563
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003564 if (!defsrv) {
3565 if (newsrv->state & SRV_BACKUP)
3566 curproxy->srv_bck++;
3567 else
3568 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003569
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003570 newsrv->prev_state = newsrv->state;
3571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
3573 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003574 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 int facility;
3576
3577 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3578 curproxy->logfac1 = global.logfac1;
3579 curproxy->logsrv1 = global.logsrv1;
3580 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003581 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 curproxy->logfac2 = global.logfac2;
3583 curproxy->logsrv2 = global.logsrv2;
3584 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003585 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
3587 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003588 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589
3590 facility = get_log_facility(args[2]);
3591 if (facility < 0) {
3592 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3593 exit(1);
3594 }
3595
3596 level = 7; /* max syslog level = debug */
3597 if (*(args[3])) {
3598 level = get_log_level(args[3]);
3599 if (level < 0) {
3600 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3601 exit(1);
3602 }
3603 }
3604
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003605 minlvl = 0; /* limit syslog level to this level (emerg) */
3606 if (*(args[4])) {
3607 minlvl = get_log_level(args[4]);
3608 if (level < 0) {
3609 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3610 exit(1);
3611 }
3612 }
3613
Robert Tsai81ae1952007-12-05 10:47:29 +01003614 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003615 struct sockaddr_un *sk = str2sun(args[1]);
3616 if (!sk) {
3617 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3618 args[1], (int)sizeof(sk->sun_path) - 1);
3619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
3621 }
3622 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003623 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003624 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003625 struct sockaddr_in *sk = str2sa(args[1]);
3626 if (!sk) {
3627 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
3630 }
3631 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003632 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003633 if (!logsrv.u.in.sin_port) {
3634 logsrv.u.in.sin_port =
3635 htons(SYSLOG_PORT);
3636 }
3637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638
3639 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003640 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 curproxy->logfac1 = facility;
3642 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003643 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003646 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 curproxy->logfac2 = facility;
3648 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003649 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651 else {
3652 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 }
3656 }
3657 else {
3658 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3659 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
3663 }
3664 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003665 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003666 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003667
Willy Tarreau977b8e42006-12-29 14:19:17 +01003668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003670
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003672 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3673 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003677
3678 /* we must first clear any optional default setting */
3679 curproxy->options &= ~PR_O_TPXY_MASK;
3680 free(curproxy->iface_name);
3681 curproxy->iface_name = NULL;
3682 curproxy->iface_len = 0;
3683
Willy Tarreaud5191e72010-02-09 20:50:45 +01003684 sk = str2sa(args[1]);
3685 if (!sk) {
3686 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
3689 }
3690 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003692
3693 cur_arg = 2;
3694 while (*(args[cur_arg])) {
3695 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003696#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3697#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003698 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3699 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3700 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003703 }
3704#endif
3705 if (!*args[cur_arg + 1]) {
3706 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3707 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003710 }
3711
3712 if (!strcmp(args[cur_arg + 1], "client")) {
3713 curproxy->options |= PR_O_TPXY_CLI;
3714 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3715 curproxy->options |= PR_O_TPXY_CIP;
3716 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003717 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3718 if (!sk) {
3719 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003724 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003725 }
3726 global.last_checks |= LSTCHK_NETADM;
3727#if !defined(CONFIG_HAP_LINUX_TPROXY)
3728 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003729#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003730#else /* no TPROXY support */
3731 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003732 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003735#endif
3736 cur_arg += 2;
3737 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003738 }
3739
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003740 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3741#ifdef SO_BINDTODEVICE
3742 if (!*args[cur_arg + 1]) {
3743 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003747 }
3748 if (curproxy->iface_name)
3749 free(curproxy->iface_name);
3750
3751 curproxy->iface_name = strdup(args[cur_arg + 1]);
3752 curproxy->iface_len = strlen(curproxy->iface_name);
3753 global.last_checks |= LSTCHK_NETADM;
3754#else
3755 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3756 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003759#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003760 cur_arg += 2;
3761 continue;
3762 }
3763 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3764 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003769 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3770 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3771 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003776 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003782
3783 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3784 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003785 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003786 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003790 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3791 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003792 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003793 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
3796 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3798 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003799 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003800 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 }
3803 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003804 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3805 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003806 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003807 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003811 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3812 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003813 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003814 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003817 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003818 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3819 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003820 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003821 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003822 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003823 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003824 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003825 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3826 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003827 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003828 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003829 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003830 }
3831 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003832 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3833 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003834 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003835 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003836 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003839 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3841 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003845
3846 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3847 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003848 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003849 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003853 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3854 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003855 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003856 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
3859 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003860 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3861 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003862 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003863 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 }
3866 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003867 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3868 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003869 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003870 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 }
3873 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003874 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3875 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003876 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003877 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003880 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003881 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3882 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003883 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003884 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003885 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003888 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003889
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 if (curproxy == &defproxy) {
3891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 if (*(args[1]) == 0) {
3899 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003903
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003904 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3905 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3906 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3907 file, linenum, args[0]);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
3911 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3912 }
3913 else if (*args[2]) {
3914 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3915 file, linenum, args[0], args[2]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003920 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003921 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003922 wl->s = strdup(args[1]);
3923 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003924 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 }
3926 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003927 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003933
Willy Tarreauade5ec42010-01-28 19:33:49 +01003934 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3935 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003936 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003937 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003941 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3942 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003943 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003944 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 }
3947 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003948 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3949 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003950 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003951 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
3954 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003955 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
3961
Willy Tarreauade5ec42010-01-28 19:33:49 +01003962 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3963 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003964 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003965 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
3968 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3970 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003971 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 }
3975 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3977 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 }
3982 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003983 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003984
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 if (curproxy == &defproxy) {
3986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003990 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 if (*(args[1]) == 0) {
3994 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 }
3998
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003999 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4000 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4001 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4002 file, linenum, args[0]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005 }
4006 err_code |= warnif_cond_requires_req(cond, file, linenum);
4007 }
4008 else if (*args[2]) {
4009 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4010 file, linenum, args[0], args[2]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004015 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004016 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004017 wl->s = strdup(args[1]);
4018 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
4020 else if (!strcmp(args[0], "errorloc") ||
4021 !strcmp(args[0], "errorloc302") ||
4022 !strcmp(args[0], "errorloc303")) { /* error location */
4023 int errnum, errlen;
4024 char *err;
4025
Willy Tarreau977b8e42006-12-29 14:19:17 +01004026 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004028
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004030 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033 }
4034
4035 errnum = atol(args[1]);
4036 if (!strcmp(args[0], "errorloc303")) {
4037 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4038 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4039 } else {
4040 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4041 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4042 }
4043
Willy Tarreau0f772532006-12-23 20:51:41 +01004044 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4045 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004046 chunk_destroy(&curproxy->errmsg[rc]);
4047 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004048 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004051
4052 if (rc >= HTTP_ERR_SIZE) {
4053 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4054 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 free(err);
4056 }
4057 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004058 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4059 int errnum, errlen, fd;
4060 char *err;
4061 struct stat stat;
4062
4063 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004064 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004065
4066 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004067 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004070 }
4071
4072 fd = open(args[2], O_RDONLY);
4073 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4074 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4075 file, linenum, args[2], args[1]);
4076 if (fd >= 0)
4077 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004080 }
4081
Willy Tarreau27a674e2009-08-17 07:23:33 +02004082 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004083 errlen = stat.st_size;
4084 } else {
4085 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004086 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004087 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004088 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004089 }
4090
4091 err = malloc(errlen); /* malloc() must succeed during parsing */
4092 errnum = read(fd, err, errlen);
4093 if (errnum != errlen) {
4094 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4095 file, linenum, args[2], args[1]);
4096 close(fd);
4097 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004100 }
4101 close(fd);
4102
4103 errnum = atol(args[1]);
4104 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4105 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004106 chunk_destroy(&curproxy->errmsg[rc]);
4107 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004108 break;
4109 }
4110 }
4111
4112 if (rc >= HTTP_ERR_SIZE) {
4113 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4114 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004116 free(err);
4117 }
4118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004120 struct cfg_kw_list *kwl;
4121 int index;
4122
4123 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4124 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4125 if (kwl->kw[index].section != CFG_LISTEN)
4126 continue;
4127 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4128 /* prepare error message just in case */
4129 snprintf(trash, sizeof(trash),
4130 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004131 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4132 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004133 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004136 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004137 else if (rc > 0) {
4138 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_WARN;
4140 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004141 }
Willy Tarreau93893792009-07-23 13:19:11 +02004142 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004143 }
4144 }
4145 }
4146
Willy Tarreau6daf3432008-01-22 16:44:08 +01004147 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 }
Willy Tarreau93893792009-07-23 13:19:11 +02004151 out:
4152 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153}
4154
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004155int
4156cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4157{
4158
4159 int err_code = 0;
4160 const char *err;
4161
4162 if (!strcmp(args[0], "userlist")) { /* new userlist */
4163 struct userlist *newul;
4164
4165 if (!*args[1]) {
4166 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4167 file, linenum, args[0]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
4172 err = invalid_char(args[1]);
4173 if (err) {
4174 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4175 file, linenum, *err, args[0], args[1]);
4176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
4178 }
4179
4180 for (newul = userlist; newul; newul = newul->next)
4181 if (!strcmp(newul->name, args[1])) {
4182 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4183 file, linenum, args[1]);
4184 err_code |= ERR_WARN;
4185 goto out;
4186 }
4187
4188 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4189 if (!newul) {
4190 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4191 err_code |= ERR_ALERT | ERR_ABORT;
4192 goto out;
4193 }
4194
4195 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4196 newul->name = strdup(args[1]);
4197
4198 if (!newul->groupusers | !newul->name) {
4199 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4200 err_code |= ERR_ALERT | ERR_ABORT;
4201 goto out;
4202 }
4203
4204 newul->next = userlist;
4205 userlist = newul;
4206
4207 } else if (!strcmp(args[0], "group")) { /* new group */
4208 int cur_arg, i;
4209 const char *err;
4210
4211 if (!*args[1]) {
4212 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4213 file, linenum, args[0]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217
4218 err = invalid_char(args[1]);
4219 if (err) {
4220 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4221 file, linenum, *err, args[0], args[1]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225
4226 for(i = 0; i < userlist->grpcnt; i++)
4227 if (!strcmp(userlist->groups[i], args[1])) {
4228 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4229 file, linenum, args[1], userlist->name);
4230 err_code |= ERR_ALERT;
4231 goto out;
4232 }
4233
4234 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4235 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4236 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
4240
4241 cur_arg = 2;
4242
4243 while (*args[cur_arg]) {
4244 if (!strcmp(args[cur_arg], "users")) {
4245 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4246 cur_arg += 2;
4247 continue;
4248 } else {
4249 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4250 file, linenum, args[0]);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254 }
4255
4256 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4257 } else if (!strcmp(args[0], "user")) { /* new user */
4258 struct auth_users *newuser;
4259 int cur_arg;
4260
4261 if (!*args[1]) {
4262 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4263 file, linenum, args[0]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
4267
4268 for (newuser = userlist->users; newuser; newuser = newuser->next)
4269 if (!strcmp(newuser->user, args[1])) {
4270 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4271 file, linenum, args[1], userlist->name);
4272 err_code |= ERR_ALERT;
4273 goto out;
4274 }
4275
4276 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4277 if (!newuser) {
4278 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4279 err_code |= ERR_ALERT | ERR_ABORT;
4280 goto out;
4281 }
4282
4283 newuser->user = strdup(args[1]);
4284
4285 newuser->next = userlist->users;
4286 userlist->users = newuser;
4287
4288 cur_arg = 2;
4289
4290 while (*args[cur_arg]) {
4291 if (!strcmp(args[cur_arg], "password")) {
4292#ifndef CONFIG_HAP_CRYPT
4293 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4294 file, linenum);
4295 err_code |= ERR_ALERT;
4296#endif
4297 newuser->pass = strdup(args[cur_arg + 1]);
4298 cur_arg += 2;
4299 continue;
4300 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4301 newuser->pass = strdup(args[cur_arg + 1]);
4302 newuser->flags |= AU_O_INSECURE;
4303 cur_arg += 2;
4304 continue;
4305 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004306 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004307 cur_arg += 2;
4308 continue;
4309 } else {
4310 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4311 file, linenum, args[0]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315 }
4316 } else {
4317 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 }
4320
4321out:
4322 return err_code;
4323}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324
4325/*
4326 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004327 * Returns the error code, 0 if OK, or any combination of :
4328 * - ERR_ABORT: must abort ASAP
4329 * - ERR_FATAL: we can continue parsing but not start the service
4330 * - ERR_WARN: a warning has been emitted
4331 * - ERR_ALERT: an alert has been emitted
4332 * Only the two first ones can stop processing, the two others are just
4333 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004335int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004337 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 FILE *f;
4339 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004341 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342
Willy Tarreaubaaee002006-06-26 02:48:02 +02004343 if ((f=fopen(file,"r")) == NULL)
4344 return -1;
4345
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004346 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004347 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004348 char *end;
4349 char *args[MAX_LINE_ARGS + 1];
4350 char *line = thisline;
4351
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 linenum++;
4353
4354 end = line + strlen(line);
4355
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004356 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4357 /* Check if we reached the limit and the last char is not \n.
4358 * Watch out for the last line without the terminating '\n'!
4359 */
4360 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004361 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004362 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004363 }
4364
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004366 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 line++;
4368
4369 arg = 0;
4370 args[arg] = line;
4371
4372 while (*line && arg < MAX_LINE_ARGS) {
4373 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4374 * C equivalent value. Other combinations left unchanged (eg: \1).
4375 */
4376 if (*line == '\\') {
4377 int skip = 0;
4378 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4379 *line = line[1];
4380 skip = 1;
4381 }
4382 else if (line[1] == 'r') {
4383 *line = '\r';
4384 skip = 1;
4385 }
4386 else if (line[1] == 'n') {
4387 *line = '\n';
4388 skip = 1;
4389 }
4390 else if (line[1] == 't') {
4391 *line = '\t';
4392 skip = 1;
4393 }
4394 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004395 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 unsigned char hex1, hex2;
4397 hex1 = toupper(line[2]) - '0';
4398 hex2 = toupper(line[3]) - '0';
4399 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4400 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4401 *line = (hex1<<4) + hex2;
4402 skip = 3;
4403 }
4404 else {
4405 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 }
4408 }
4409 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004410 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 end -= skip;
4412 }
4413 line++;
4414 }
4415 else if (*line == '#' || *line == '\n' || *line == '\r') {
4416 /* end of string, end of loop */
4417 *line = 0;
4418 break;
4419 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004420 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004422 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004423 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 line++;
4425 args[++arg] = line;
4426 }
4427 else {
4428 line++;
4429 }
4430 }
4431
4432 /* empty line */
4433 if (!**args)
4434 continue;
4435
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004436 if (*line) {
4437 /* we had to stop due to too many args.
4438 * Let's terminate the string, print the offending part then cut the
4439 * last arg.
4440 */
4441 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4442 line++;
4443 *line = '\0';
4444
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004445 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004446 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 args[arg] = line;
4449 }
4450
Willy Tarreau540abe42007-05-02 20:50:16 +02004451 /* zero out remaining args and ensure that at least one entry
4452 * is zeroed out.
4453 */
4454 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 args[arg] = line;
4456 }
4457
Willy Tarreau3842f002009-06-14 11:39:52 +02004458 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004459 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004460 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004461 for (arg=0; *args[arg+1]; arg++)
4462 args[arg] = args[arg+1]; // shift args after inversion
4463 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004464 else if (!strcmp(args[0], "default")) {
4465 kwm = KWM_DEF;
4466 for (arg=0; *args[arg+1]; arg++)
4467 args[arg] = args[arg+1]; // shift args after inversion
4468 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004469
Willy Tarreau3842f002009-06-14 11:39:52 +02004470 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4471 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004472 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004473 }
4474
Willy Tarreau977b8e42006-12-29 14:19:17 +01004475 if (!strcmp(args[0], "listen") ||
4476 !strcmp(args[0], "frontend") ||
4477 !strcmp(args[0], "backend") ||
4478 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004479 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004481 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004482 cursection = strdup(args[0]);
4483 }
4484 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004486 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004487 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004488 } else if (!strcmp(args[0], "userlist")) {
4489 confsect = CFG_USERLIST;
4490 free(cursection);
4491 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 /* else it's a section keyword */
4494
4495 switch (confsect) {
4496 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 break;
4499 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004500 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004502 case CFG_USERLIST:
4503 err_code |= cfg_parse_users(file, linenum, args, kwm);
4504 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004506 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004509
4510 if (err_code & ERR_ABORT)
4511 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004513 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004514 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004516 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517}
4518
Willy Tarreaubb925012009-07-23 13:36:36 +02004519/*
4520 * Returns the error code, 0 if OK, or any combination of :
4521 * - ERR_ABORT: must abort ASAP
4522 * - ERR_FATAL: we can continue parsing but not start the service
4523 * - ERR_WARN: a warning has been emitted
4524 * - ERR_ALERT: an alert has been emitted
4525 * Only the two first ones can stop processing, the two others are just
4526 * indicators.
4527 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004528int check_config_validity()
4529{
4530 int cfgerr = 0;
4531 struct proxy *curproxy = NULL;
4532 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004533 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004534 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004535 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536
4537 /*
4538 * Now, check for the integrity of all that we have collected.
4539 */
4540
4541 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004542 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004544 /* first, we will invert the proxy list order */
4545 curproxy = NULL;
4546 while (proxy) {
4547 struct proxy *next;
4548
4549 next = proxy->next;
4550 proxy->next = curproxy;
4551 curproxy = proxy;
4552 if (!next)
4553 break;
4554 proxy = next;
4555 }
4556
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004558 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 }
4562
4563 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004564 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004565 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004566 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004567 unsigned int next_id;
4568
4569 if (!curproxy->uuid) {
4570 /* proxy ID not set, use automatic numbering with first
4571 * spare entry starting with next_pxid.
4572 */
4573 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4574 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4575 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004576 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004577 next_pxid++;
4578
Willy Tarreau55ea7572007-06-17 19:56:27 +02004579
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004581 /* ensure we don't keep listeners uselessly bound */
4582 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 curproxy = curproxy->next;
4584 continue;
4585 }
4586
Willy Tarreauff01a212009-03-15 13:46:16 +01004587 switch (curproxy->mode) {
4588 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004589 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004590 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004591 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004593 cfgerr++;
4594 }
4595
4596 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004597 Warning("config : servers will be ignored for %s '%s'.\n",
4598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004599 break;
4600
4601 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004602 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004603 break;
4604
4605 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004606 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004607 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004608 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4609 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004610 cfgerr++;
4611 }
4612 break;
4613 }
4614
4615 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004616 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4617 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 cfgerr++;
4619 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004620
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004621 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004622 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004623 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004624 Alert("config : %s '%s' cannot use both transparent and 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#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004629 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004630 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4631 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004632 cfgerr++;
4633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004635 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004636 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4637 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004638 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004639 }
4640 }
4641 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4642 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4643 /* If no LB algo is set in a backend, and we're not in
4644 * transparent mode, dispatch mode nor proxy mode, we
4645 * want to use balance roundrobin by default.
4646 */
4647 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4648 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 }
4650 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004651
Willy Tarreau82936582007-11-30 15:20:09 +01004652 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4653 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004654 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4655 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004656 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004657 }
4658
Willy Tarreauef781042010-01-27 11:53:01 +01004659 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4660 curproxy->options &= ~PR_O2_CHK_SNDST;
4661 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4662 "send-state", proxy_type_str(curproxy), curproxy->id);
4663 err_code |= ERR_WARN;
4664 }
4665
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004666 /* if a default backend was specified, let's find it */
4667 if (curproxy->defbe.name) {
4668 struct proxy *target;
4669
Alex Williams96532db2009-11-01 21:27:13 -05004670 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004671 if (!target) {
4672 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4673 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004674 cfgerr++;
4675 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004676 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4677 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004678 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004679 } else {
4680 free(curproxy->defbe.name);
4681 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004682 /* we force the backend to be present on at least all of
4683 * the frontend's processes.
4684 */
4685 target->bind_proc = curproxy->bind_proc ?
4686 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 }
4689
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004690 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004691 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4692 /* map jump target for ACT_SETBE in req_rep chain */
4693 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004694 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004695 struct proxy *target;
4696
Willy Tarreaua496b602006-12-17 23:15:24 +01004697 if (exp->action != ACT_SETBE)
4698 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004699
Alex Williams96532db2009-11-01 21:27:13 -05004700 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004701 if (!target) {
4702 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4703 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004704 cfgerr++;
4705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004706 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4707 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004708 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004709 } else {
4710 free((void *)exp->replace);
4711 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004712 /* we force the backend to be present on at least all of
4713 * the frontend's processes.
4714 */
4715 target->bind_proc = curproxy->bind_proc ?
4716 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004717 }
4718 }
4719 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004720
4721 /* find the target proxy for 'use_backend' rules */
4722 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004723 struct proxy *target;
4724
Alex Williams96532db2009-11-01 21:27:13 -05004725 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004726
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004727 if (!target) {
4728 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4729 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004730 cfgerr++;
4731 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004732 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4733 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004734 cfgerr++;
4735 } else {
4736 free((void *)rule->be.name);
4737 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004738 /* we force the backend to be present on at least all of
4739 * the frontend's processes.
4740 */
4741 target->bind_proc = curproxy->bind_proc ?
4742 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004743 }
4744 }
4745
Emeric Brunb982a3d2010-01-04 15:45:53 +01004746 /* find the target table for 'stick' rules */
4747 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4748 struct proxy *target;
4749
Emeric Brun1d33b292010-01-04 15:47:17 +01004750 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4751 if (mrule->flags & STK_IS_STORE)
4752 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4753
Emeric Brunb982a3d2010-01-04 15:45:53 +01004754 if (mrule->table.name)
4755 target = findproxy(mrule->table.name, PR_CAP_BE);
4756 else
4757 target = curproxy;
4758
4759 if (!target) {
4760 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4761 curproxy->id, mrule->table.name);
4762 cfgerr++;
4763 }
4764 else if (target->table.size == 0) {
4765 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4766 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4767 cfgerr++;
4768 }
4769 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4770 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4771 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4772 cfgerr++;
4773 }
4774 else {
4775 free((void *)mrule->table.name);
4776 mrule->table.t = &(target->table);
4777 }
4778 }
4779
4780 /* find the target table for 'store response' rules */
4781 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4782 struct proxy *target;
4783
Emeric Brun1d33b292010-01-04 15:47:17 +01004784 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4785
Emeric Brunb982a3d2010-01-04 15:45:53 +01004786 if (mrule->table.name)
4787 target = findproxy(mrule->table.name, PR_CAP_BE);
4788 else
4789 target = curproxy;
4790
4791 if (!target) {
4792 Alert("Proxy '%s': unable to find store table '%s'.\n",
4793 curproxy->id, mrule->table.name);
4794 cfgerr++;
4795 }
4796 else if (target->table.size == 0) {
4797 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4798 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4799 cfgerr++;
4800 }
4801 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4802 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4803 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4804 cfgerr++;
4805 }
4806 else {
4807 free((void *)mrule->table.name);
4808 mrule->table.t = &(target->table);
4809 }
4810 }
4811
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004812 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4813 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004814 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4815 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4816 "proxy", curproxy->id);
4817 cfgerr++;
4818 goto out_uri_auth_compat;
4819 }
4820
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004821 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004822 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004823 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004824 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004825
Willy Tarreau95fa4692010-02-01 13:05:50 +01004826 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4827 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004828
4829 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004830 uri_auth_compat_req[i++] = "realm";
4831 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4832 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004833
Willy Tarreau95fa4692010-02-01 13:05:50 +01004834 uri_auth_compat_req[i++] = "unless";
4835 uri_auth_compat_req[i++] = "{";
4836 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4837 uri_auth_compat_req[i++] = "}";
4838 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004839
Willy Tarreau95fa4692010-02-01 13:05:50 +01004840 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4841 if (!req_acl) {
4842 cfgerr++;
4843 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004844 }
4845
Willy Tarreau95fa4692010-02-01 13:05:50 +01004846 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4847
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004848 if (curproxy->uri_auth->auth_realm) {
4849 free(curproxy->uri_auth->auth_realm);
4850 curproxy->uri_auth->auth_realm = NULL;
4851 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004852
4853 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004854 }
4855out_uri_auth_compat:
4856
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004857 cfgerr += acl_find_targets(curproxy);
4858
Willy Tarreau2738a142006-07-08 17:28:09 +02004859 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004860 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004861 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004862 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004863 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004864 " | While not properly invalid, you will certainly encounter various problems\n"
4865 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004866 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004867 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004868 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004869 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004870
Willy Tarreau1fa31262007-12-03 00:36:16 +01004871 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4872 * We must still support older configurations, so let's find out whether those
4873 * parameters have been set or must be copied from contimeouts.
4874 */
4875 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004876 if (!curproxy->timeout.tarpit ||
4877 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004878 /* tarpit timeout not set. We search in the following order:
4879 * default.tarpit, curr.connect, default.connect.
4880 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004881 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004882 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004883 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004884 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004885 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004886 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004887 }
4888 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004889 (!curproxy->timeout.queue ||
4890 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004891 /* queue timeout not set. We search in the following order:
4892 * default.queue, curr.connect, default.connect.
4893 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004894 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004895 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004896 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004897 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004898 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004899 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004900 }
4901 }
4902
Willy Tarreauf3c69202006-07-09 16:42:34 +02004903 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004904 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4905 curproxy->check_req = (char *)malloc(curproxy->check_len);
4906 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004907 }
4908
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004909 /* The small pools required for the capture lists */
4910 if (curproxy->nb_req_cap)
4911 curproxy->req_cap_pool = create_pool("ptrcap",
4912 curproxy->nb_req_cap * sizeof(char *),
4913 MEM_F_SHARED);
4914 if (curproxy->nb_rsp_cap)
4915 curproxy->rsp_cap_pool = create_pool("ptrcap",
4916 curproxy->nb_rsp_cap * sizeof(char *),
4917 MEM_F_SHARED);
4918
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004919 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4920 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4921 MEM_F_SHARED);
4922
Willy Tarreau86034312006-12-29 00:10:33 +01004923 /* for backwards compatibility with "listen" instances, if
4924 * fullconn is not set but maxconn is set, then maxconn
4925 * is used.
4926 */
4927 if (!curproxy->fullconn)
4928 curproxy->fullconn = curproxy->maxconn;
4929
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 /* first, we will invert the servers list order */
4931 newsrv = NULL;
4932 while (curproxy->srv) {
4933 struct server *next;
4934
4935 next = curproxy->srv->next;
4936 curproxy->srv->next = newsrv;
4937 newsrv = curproxy->srv;
4938 if (!next)
4939 break;
4940 curproxy->srv = next;
4941 }
4942
Willy Tarreau20697042007-11-15 23:26:18 +01004943 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004944 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004946 /* We have to initialize the server lookup mechanism depending
4947 * on what LB algorithm was choosen.
4948 */
4949
4950 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4951 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4952 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004953 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4954 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4955 init_server_map(curproxy);
4956 } else {
4957 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4958 fwrr_init_server_groups(curproxy);
4959 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004960 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004961
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004962 case BE_LB_KIND_LC:
4963 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004964 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004965 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004966
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004967 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004968 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4969 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4970 chash_init_server_tree(curproxy);
4971 } else {
4972 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4973 init_server_map(curproxy);
4974 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004975 break;
4976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977
4978 if (curproxy->options & PR_O_LOGASAP)
4979 curproxy->to_log &= ~LW_BYTES;
4980
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004981 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4982 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4983 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4984 proxy_type_str(curproxy), curproxy->id);
4985 err_code |= ERR_WARN;
4986 }
4987
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004989 * ensure that we're not cross-dressing a TCP server into HTTP.
4990 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004991 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004992 newsrv = curproxy->srv;
4993 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004994 if (!newsrv->puid) {
4995 /* server ID not set, use automatic numbering with first
4996 * spare entry starting with next_svid.
4997 */
4998 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4999 newsrv->conf.id.key = newsrv->puid = next_id;
5000 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005001 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005002 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005003
Willy Tarreau21d2af32008-02-14 20:25:24 +01005004 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005005 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5006 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005007 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005008 }
5009 newsrv = newsrv->next;
5010 }
5011
5012 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 * If this server supports a maxconn parameter, it needs a dedicated
5014 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005015 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 */
5017 newsrv = curproxy->srv;
5018 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005019 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 /* Only 'minconn' was specified, or it was higher than or equal
5021 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5022 * this will avoid further useless expensive computations.
5023 */
5024 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005025 } else if (newsrv->maxconn && !newsrv->minconn) {
5026 /* minconn was not specified, so we set it to maxconn */
5027 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005028 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005029 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5030 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005031 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
5033
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005034 if (newsrv->trackit) {
5035 struct proxy *px;
5036 struct server *srv;
5037 char *pname, *sname;
5038
5039 pname = newsrv->trackit;
5040 sname = strrchr(pname, '/');
5041
5042 if (sname)
5043 *sname++ = '\0';
5044 else {
5045 sname = pname;
5046 pname = NULL;
5047 }
5048
5049 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005050 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005051 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005052 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5053 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005054 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005055 cfgerr++;
5056 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005057 }
5058 } else
5059 px = curproxy;
5060
5061 srv = findserver(px, sname);
5062 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005063 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5064 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005065 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005066 cfgerr++;
5067 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005068 }
5069
5070 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005071 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005072 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005073 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005074 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005075 cfgerr++;
5076 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005077 }
5078
5079 if (curproxy != px &&
5080 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005081 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005082 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005083 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005084 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005085 cfgerr++;
5086 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005087 }
5088
5089 newsrv->tracked = srv;
5090 newsrv->tracknext = srv->tracknext;
5091 srv->tracknext = newsrv;
5092
5093 free(newsrv->trackit);
5094 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005095 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 newsrv = newsrv->next;
5097 }
5098
Willy Tarreauc1a21672009-08-16 22:37:44 +02005099 if (curproxy->cap & PR_CAP_FE) {
5100 if (curproxy->tcp_req.inspect_delay ||
5101 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5102 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5103
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005104 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005105 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005106 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005107 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005108
5109 /* both TCP and HTTP must check switching rules */
5110 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5111 }
5112
5113 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005114 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005115 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005116 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005117 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005118
Emeric Brunb982a3d2010-01-04 15:45:53 +01005119 /* init table on backend capabilities proxy */
5120 stktable_init(&curproxy->table);
5121
Willy Tarreauc1a21672009-08-16 22:37:44 +02005122 /* If the backend does requires RDP cookie persistence, we have to
5123 * enable the corresponding analyser.
5124 */
5125 if (curproxy->options2 & PR_O2_RDPC_PRST)
5126 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5127 }
5128
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005129 listener = NULL;
5130 while (curproxy->listen) {
5131 struct listener *next;
5132
5133 next = curproxy->listen->next;
5134 curproxy->listen->next = listener;
5135 listener = curproxy->listen;
5136
5137 if (!next)
5138 break;
5139
5140 curproxy->listen = next;
5141 }
5142
Willy Tarreaue6b98942007-10-29 01:09:36 +01005143 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005144 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005145 listener = curproxy->listen;
5146 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005147 if (!listener->luid) {
5148 /* listener ID not set, use automatic numbering with first
5149 * spare entry starting with next_luid.
5150 */
5151 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5152 listener->conf.id.key = listener->luid = next_id;
5153 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005154 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005155 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005156
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005157 /* enable separate counters */
5158 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5159 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5160 if (!listener->name) {
5161 sprintf(trash, "sock-%d", listener->luid);
5162 listener->name = strdup(trash);
5163 }
5164 }
5165
Willy Tarreaue6b98942007-10-29 01:09:36 +01005166 if (curproxy->options & PR_O_TCP_NOLING)
5167 listener->options |= LI_O_NOLINGER;
5168 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005169 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005170 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005171 listener->accept = event_accept;
5172 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005173 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005174 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005175
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005176 /* smart accept mode is automatic in HTTP mode */
5177 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5178 (curproxy->mode == PR_MODE_HTTP &&
5179 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5180 listener->options |= LI_O_NOQUICKACK;
5181
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005182 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005183 listener = listener->next;
5184 }
5185
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 curproxy = curproxy->next;
5187 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005188
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005189 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5190 struct auth_users *curuser;
5191 int g;
5192
5193 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5194 unsigned int group_mask = 0;
5195 char *group = NULL;
5196
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005197 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005198 continue;
5199
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005200 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005201
5202 for (g = 0; g < curuserlist->grpcnt; g++)
5203 if (!strcmp(curuserlist->groups[g], group))
5204 break;
5205
5206 if (g == curuserlist->grpcnt) {
5207 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5208 curuserlist->name, group, curuser->user);
5209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
5211 }
5212
5213 group_mask |= (1 << g);
5214 }
5215
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005216 free(curuser->u.groups);
5217 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005218 }
5219
5220 for (g = 0; g < curuserlist->grpcnt; g++) {
5221 char *user = NULL;
5222
5223 if (!curuserlist->groupusers[g])
5224 continue;
5225
5226 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5227 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5228 if (!strcmp(curuser->user, user))
5229 break;
5230
5231 if (!curuser) {
5232 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5233 curuserlist->name, user, curuserlist->groups[g]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005238 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005239 }
5240
5241 free(curuserlist->groupusers[g]);
5242 }
5243
5244 free(curuserlist->groupusers);
5245
5246#ifdef DEBUG_AUTH
5247 for (g = 0; g < curuserlist->grpcnt; g++) {
5248 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5249
5250 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5251 if (curuser->group_mask & (1 << g))
5252 fprintf(stderr, " %s", curuser->user);
5253 }
5254
5255 fprintf(stderr, "\n");
5256 }
5257#endif
5258
5259 }
5260
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005261 /*
5262 * Recount currently required checks.
5263 */
5264
5265 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5266 int optnum;
5267
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005268 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5269 if (curproxy->options & cfg_opts[optnum].val)
5270 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005271
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005272 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5273 if (curproxy->options2 & cfg_opts2[optnum].val)
5274 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005275 }
5276
Willy Tarreaubb925012009-07-23 13:36:36 +02005277 if (cfgerr > 0)
5278 err_code |= ERR_ALERT | ERR_FATAL;
5279 out:
5280 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281}
5282
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005283/*
5284 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5285 * parsing sessions.
5286 */
5287void cfg_register_keywords(struct cfg_kw_list *kwl)
5288{
5289 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5290}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005292/*
5293 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5294 */
5295void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5296{
5297 LIST_DEL(&kwl->list);
5298 LIST_INIT(&kwl->list);
5299}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300
5301/*
5302 * Local variables:
5303 * c-indent-level: 8
5304 * c-basic-offset: 8
5305 * End:
5306 */