blob: 9bdfb3e3d579a03cf09a90e1220b3aeb74fe1d97 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
730 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
731 break;
732 }
733
734 if (!i || args[1][i]) {
735 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
736 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
737 file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741
742 if (global.node)
743 free(global.node);
744
745 global.node = strdup(args[1]);
746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 else if (!strcmp(args[0], "pidfile")) {
748 if (global.pidfile != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.pidfile = strdup(args[1]);
759 }
760 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200762 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763
764 if (*(args[1]) == 0 || *(args[2]) == 0) {
765 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT | ERR_FATAL;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769
770 facility = get_log_facility(args[2]);
771 if (facility < 0) {
772 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776
777 level = 7; /* max syslog level = debug */
778 if (*(args[3])) {
779 level = get_log_level(args[3]);
780 if (level < 0) {
781 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 }
786
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200787 minlvl = 0; /* limit syslog level to this level (emerg) */
788 if (*(args[4])) {
789 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200791 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200794 }
795 }
796
Robert Tsai81ae1952007-12-05 10:47:29 +0100797 if (args[1][0] == '/') {
798 logsrv.u.addr.sa_family = AF_UNIX;
799 logsrv.u.un = *str2sun(args[1]);
800 } else {
801 logsrv.u.addr.sa_family = AF_INET;
802 logsrv.u.in = *str2sa(args[1]);
803 if (!logsrv.u.in.sin_port)
804 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806
807 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 global.logfac1 = facility;
810 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200811 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100814 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 global.logfac2 = facility;
816 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200817 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 else {
820 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200823 }
824 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
825 if (global.spread_checks != 0) {
826 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200827 err_code |= ERR_ALERT;
828 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200829 }
830 if (*(args[1]) == 0) {
831 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200834 }
835 global.spread_checks = atol(args[1]);
836 if (global.spread_checks < 0 || global.spread_checks > 50) {
837 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200842 struct cfg_kw_list *kwl;
843 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200844 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200845
846 list_for_each_entry(kwl, &cfg_keywords.list, list) {
847 for (index = 0; kwl->kw[index].kw != NULL; index++) {
848 if (kwl->kw[index].section != CFG_GLOBAL)
849 continue;
850 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
851 /* prepare error message just in case */
852 snprintf(trash, sizeof(trash),
853 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200854 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
855 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200858 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200859 else if (rc > 0) {
860 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200861 err_code |= ERR_WARN;
862 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200863 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200864 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200865 }
866 }
867 }
868
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200872
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 out:
874 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875}
876
Willy Tarreau97cb7802010-01-03 20:23:58 +0100877/* Perform the most basic initialization of a proxy :
878 * memset(), list_init(*), reset_timeouts(*).
879 */
880static void init_new_proxy(struct proxy *p)
881{
882 memset(p, 0, sizeof(struct proxy));
883 LIST_INIT(&p->pendconns);
884 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100885 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100886 LIST_INIT(&p->block_cond);
887 LIST_INIT(&p->redirect_rules);
888 LIST_INIT(&p->mon_fail_cond);
889 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100890 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100891 LIST_INIT(&p->sticking_rules);
892 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100893 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100894 LIST_INIT(&p->req_add);
895 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100896
897 /* Timeouts are defined as -1 */
898 proxy_reset_timeouts(p);
899}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200901void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100903 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 defproxy.mode = PR_MODE_TCP;
905 defproxy.state = PR_STNEW;
906 defproxy.maxconn = cfg_maxpconn;
907 defproxy.conn_retries = CONN_RETRIES;
908 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100909
910 defproxy.defsrv.inter = DEF_CHKINTR;
911 defproxy.defsrv.fastinter = 0;
912 defproxy.defsrv.downinter = 0;
913 defproxy.defsrv.rise = DEF_RISETIME;
914 defproxy.defsrv.fall = DEF_FALLTIME;
915 defproxy.defsrv.check_port = 0;
916 defproxy.defsrv.maxqueue = 0;
917 defproxy.defsrv.minconn = 0;
918 defproxy.defsrv.maxconn = 0;
919 defproxy.defsrv.slowstart = 0;
920 defproxy.defsrv.onerror = DEF_HANA_ONERR;
921 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
922 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923}
924
Willy Tarreauade5ec42010-01-28 19:33:49 +0100925
926static int create_cond_regex_rule(const char *file, int line,
927 struct proxy *px, int dir, int action, int flags,
928 const char *cmd, const char *reg, const char *repl,
929 const char **cond_start)
930{
931 regex_t *preg = NULL;
932 const char *err;
933 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100934 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100935
936 if (px == &defproxy) {
937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto err;
940 }
941
942 if (*reg == 0) {
943 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto err;
946 }
947
948 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
949 err_code |= ERR_WARN;
950
Willy Tarreau5321c422010-01-28 20:35:13 +0100951 if (cond_start &&
952 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
953 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
954 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
955 file, line, cmd);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto err;
958 }
959 }
960 else if (cond_start && **cond_start) {
961 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
962 file, line, cmd, *cond_start);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto err;
965 }
966
967 if (dir == ACL_DIR_REQ)
968 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100969 else
970 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100971
Willy Tarreauade5ec42010-01-28 19:33:49 +0100972 preg = calloc(1, sizeof(regex_t));
973 if (!preg) {
974 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
975 err_code = ERR_ALERT | ERR_FATAL;
976 goto err;
977 }
978
979 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
980 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
981 err_code = ERR_ALERT | ERR_FATAL;
982 goto err;
983 }
984
985 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100986 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +0100987 if (repl && err) {
988 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
989 file, line, cmd, *err);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto err;
992 }
993
994 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
995 err_code |= ERR_WARN;
996
997 return err_code;
998 err:
999 free(preg);
1000 return err_code;
1001}
1002
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001004 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001005 * Returns the error code, 0 if OK, or any combination of :
1006 * - ERR_ABORT: must abort ASAP
1007 * - ERR_FATAL: we can continue parsing but not start the service
1008 * - ERR_WARN: a warning has been emitted
1009 * - ERR_ALERT: an alert has been emitted
1010 * Only the two first ones can stop processing, the two others are just
1011 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001013int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014{
1015 static struct proxy *curproxy = NULL;
1016 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001017 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001018 int rc;
1019 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001020 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001021 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (!strcmp(args[0], "listen"))
1024 rc = PR_CAP_LISTEN;
1025 else if (!strcmp(args[0], "frontend"))
1026 rc = PR_CAP_FE | PR_CAP_RS;
1027 else if (!strcmp(args[0], "backend"))
1028 rc = PR_CAP_BE | PR_CAP_RS;
1029 else if (!strcmp(args[0], "ruleset"))
1030 rc = PR_CAP_RS;
1031 else
1032 rc = PR_CAP_NONE;
1033
1034 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001035 if (!*args[1]) {
1036 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1037 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001039 err_code |= ERR_ALERT | ERR_ABORT;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001042
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001043 err = invalid_char(args[1]);
1044 if (err) {
1045 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1046 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001048 }
1049
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001050 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1051 /*
1052 * If there are two proxies with the same name only following
1053 * combinations are allowed:
1054 *
1055 * listen backend frontend ruleset
1056 * listen - - - -
1057 * backend - - OK -
1058 * frontend - OK - -
1059 * ruleset - - - -
1060 */
1061
1062 if (!strcmp(curproxy->id, args[1]) &&
1063 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1064 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001065 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1066 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1067 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001068 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001069 }
1070 }
1071
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1073 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001074 err_code |= ERR_ALERT | ERR_ABORT;
1075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001076 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001077
Willy Tarreau97cb7802010-01-03 20:23:58 +01001078 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 curproxy->next = proxy;
1080 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001081 curproxy->conf.file = file;
1082 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001083 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086
1087 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001088 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001089 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001090 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_FATAL;
1092 goto out;
1093 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001094 new = curproxy->listen;
1095 while (new != last) {
1096 new->conf.file = file;
1097 new->conf.line = linenum;
1098 new = new->next;
1099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 global.maxsock++;
1101 }
1102
1103 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001104 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001108 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001109 curproxy->no_options = defproxy.no_options;
1110 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001111 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001112 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001113 curproxy->except_net = defproxy.except_net;
1114 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001115 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001116 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001118 if (defproxy.fwdfor_hdr_len) {
1119 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1120 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1121 }
1122
Willy Tarreaub86db342009-11-30 11:50:16 +01001123 if (defproxy.orgto_hdr_len) {
1124 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1125 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1126 }
1127
Willy Tarreau977b8e42006-12-29 14:19:17 +01001128 if (curproxy->cap & PR_CAP_FE) {
1129 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001130 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001131 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001132
1133 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001134 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1135 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001136
1137 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139
Willy Tarreau977b8e42006-12-29 14:19:17 +01001140 if (curproxy->cap & PR_CAP_BE) {
1141 curproxy->fullconn = defproxy.fullconn;
1142 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143
Willy Tarreau977b8e42006-12-29 14:19:17 +01001144 if (defproxy.check_req)
1145 curproxy->check_req = strdup(defproxy.check_req);
1146 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (defproxy.cookie_name)
1149 curproxy->cookie_name = strdup(defproxy.cookie_name);
1150 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001151 if (defproxy.cookie_domain)
1152 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001153
Emeric Brun647caf12009-06-30 17:57:00 +02001154 if (defproxy.rdp_cookie_name)
1155 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1156 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1157
Willy Tarreau01732802007-11-01 22:48:15 +01001158 if (defproxy.url_param_name)
1159 curproxy->url_param_name = strdup(defproxy.url_param_name);
1160 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001161
Benoitaffb4812009-03-25 13:02:10 +01001162 if (defproxy.hh_name)
1163 curproxy->hh_name = strdup(defproxy.hh_name);
1164 curproxy->hh_len = defproxy.hh_len;
1165 curproxy->hh_match_domain = defproxy.hh_match_domain;
1166
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001167 if (defproxy.iface_name)
1168 curproxy->iface_name = strdup(defproxy.iface_name);
1169 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001172 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001173 if (defproxy.capture_name)
1174 curproxy->capture_name = strdup(defproxy.capture_name);
1175 curproxy->capture_namelen = defproxy.capture_namelen;
1176 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178
Willy Tarreau977b8e42006-12-29 14:19:17 +01001179 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001180 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001181 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001182 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001183 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 curproxy->uri_auth = defproxy.uri_auth;
1185 curproxy->mon_net = defproxy.mon_net;
1186 curproxy->mon_mask = defproxy.mon_mask;
1187 if (defproxy.monitor_uri)
1188 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1189 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001190 if (defproxy.defbe.name)
1191 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001192 }
1193
1194 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001195 curproxy->timeout.connect = defproxy.timeout.connect;
1196 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001197 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001198 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001199 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001200 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001201 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001202 curproxy->source_addr = defproxy.source_addr;
1203 }
1204
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 curproxy->mode = defproxy.mode;
1206 curproxy->logfac1 = defproxy.logfac1;
1207 curproxy->logsrv1 = defproxy.logsrv1;
1208 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001209 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 curproxy->logfac2 = defproxy.logfac2;
1211 curproxy->logsrv2 = defproxy.logsrv2;
1212 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001213 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001215 curproxy->conf.used_listener_id = EB_ROOT;
1216 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001217
Willy Tarreau93893792009-07-23 13:19:11 +02001218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 }
1220 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1221 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001222 /* FIXME-20070101: we should do this too at the end of the
1223 * config parsing to free all default values.
1224 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001225 free(defproxy.check_req);
1226 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001227 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001228 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001229 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001230 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001231 free(defproxy.capture_name);
1232 free(defproxy.monitor_uri);
1233 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001234 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001235 free(defproxy.fwdfor_hdr_name);
1236 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001237 free(defproxy.orgto_hdr_name);
1238 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001239
Willy Tarreaua534fea2008-08-03 12:19:50 +02001240 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001241 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001242
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 /* we cannot free uri_auth because it might already be used */
1244 init_default_instance();
1245 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001246 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 }
1249 else if (curproxy == NULL) {
1250 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
1254
Willy Tarreau977b8e42006-12-29 14:19:17 +01001255
1256 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001258 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001259 int cur_arg;
1260
Willy Tarreaubaaee002006-06-26 02:48:02 +02001261 if (curproxy == &defproxy) {
1262 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001266 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268
1269 if (strchr(args[1], ':') == NULL) {
1270 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001275
1276 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001277 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001281
Willy Tarreau90a570f2009-10-04 20:54:54 +02001282 new_listen = curproxy->listen;
1283 while (new_listen != last_listen) {
1284 new_listen->conf.file = file;
1285 new_listen->conf.line = linenum;
1286 new_listen = new_listen->next;
1287 }
1288
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001289 cur_arg = 2;
1290 while (*(args[cur_arg])) {
1291 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1292#ifdef SO_BINDTODEVICE
1293 struct listener *l;
1294
1295 if (!*args[cur_arg + 1]) {
1296 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001300 }
1301
1302 for (l = curproxy->listen; l != last_listen; l = l->next)
1303 l->interface = strdup(args[cur_arg + 1]);
1304
1305 global.last_checks |= LSTCHK_NETADM;
1306
1307 cur_arg += 2;
1308 continue;
1309#else
1310 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1311 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001314#endif
1315 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001316 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1317#ifdef TCP_MAXSEG
1318 struct listener *l;
1319 int mss;
1320
1321 if (!*args[cur_arg + 1]) {
1322 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001326 }
1327
1328 mss = str2uic(args[cur_arg + 1]);
1329 if (mss < 1 || mss > 65535) {
1330 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001332 err_code |= ERR_ALERT | ERR_FATAL;
1333 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001334 }
1335
1336 for (l = curproxy->listen; l != last_listen; l = l->next)
1337 l->maxseg = mss;
1338
1339 cur_arg += 2;
1340 continue;
1341#else
1342 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1343 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001346#endif
1347 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001348
1349 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1350#ifdef TCP_DEFER_ACCEPT
1351 struct listener *l;
1352
1353 for (l = curproxy->listen; l != last_listen; l = l->next)
1354 l->options |= LI_O_DEF_ACCEPT;
1355
1356 cur_arg ++;
1357 continue;
1358#else
1359 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1360 file, linenum, args[0], args[cur_arg]);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363#endif
1364 }
1365
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001366 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001367#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001368 struct listener *l;
1369
1370 for (l = curproxy->listen; l != last_listen; l = l->next)
1371 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001372
1373 cur_arg ++;
1374 continue;
1375#else
1376 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1377 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001378 err_code |= ERR_ALERT | ERR_FATAL;
1379 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001382
1383 if (!strcmp(args[cur_arg], "name")) {
1384 struct listener *l;
1385
1386 for (l = curproxy->listen; l != last_listen; l = l->next)
1387 l->name = strdup(args[cur_arg + 1]);
1388
1389 cur_arg += 2;
1390 continue;
1391 }
1392
1393 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001394 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001395 struct listener *l;
1396
1397 if (curproxy->listen->next != last_listen) {
1398 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1399 file, linenum, args[cur_arg]);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto out;
1402 }
1403
1404 if (!*args[cur_arg + 1]) {
1405 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1406 file, linenum, args[cur_arg]);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto out;
1409 }
1410
1411 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001412 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001413
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001414 if (curproxy->listen->luid <= 0) {
1415 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001416 file, linenum);
1417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
1419 }
1420
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001421 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1422 if (node) {
1423 l = container_of(node, struct listener, conf.id);
1424 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1425 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1430
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001431 cur_arg += 2;
1432 continue;
1433 }
1434
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001435 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001436 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001437 err_code |= ERR_ALERT | ERR_FATAL;
1438 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
1443 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1444 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1445 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 /* flush useless bits */
1454 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001457 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001459 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460
Willy Tarreau1c47f852006-07-09 08:22:27 +02001461 if (!*args[1]) {
1462 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001466 }
1467
Willy Tarreaua534fea2008-08-03 12:19:50 +02001468 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001469 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001470 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001471 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001472 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1473
Willy Tarreau93893792009-07-23 13:19:11 +02001474 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1477 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1478 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1479 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1480 else {
1481 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
1485 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001486 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001487 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001488
1489 if (curproxy == &defproxy) {
1490 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001494 }
1495
1496 if (!*args[1]) {
1497 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001501 }
1502
1503 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001504 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001505
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001506 if (curproxy->uuid <= 0) {
1507 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001511 }
1512
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001513 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1514 if (node) {
1515 struct proxy *target = container_of(node, struct proxy, conf.id);
1516 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1517 file, linenum, proxy_type_str(curproxy), curproxy->id,
1518 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001523 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001524 else if (!strcmp(args[0], "description")) {
1525 int i, len=0;
1526 char *d;
1527
Cyril Bonté99ed3272010-01-24 23:29:44 +01001528 if (curproxy == &defproxy) {
1529 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1530 file, linenum, args[0]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001535 if (!*args[1]) {
1536 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1537 file, linenum, args[0]);
1538 return -1;
1539 }
1540
1541 for(i=1; *args[i]; i++)
1542 len += strlen(args[i])+1;
1543
1544 d = (char *)calloc(1, len);
1545 curproxy->desc = d;
1546
1547 d += sprintf(d, "%s", args[1]);
1548 for(i=2; *args[i]; i++)
1549 d += sprintf(d, " %s", args[i]);
1550
1551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1553 curproxy->state = PR_STSTOPPED;
1554 }
1555 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1556 curproxy->state = PR_STNEW;
1557 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001558 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1559 int cur_arg = 1;
1560 unsigned int set = 0;
1561
1562 while (*args[cur_arg]) {
1563 int u;
1564 if (strcmp(args[cur_arg], "all") == 0) {
1565 set = 0;
1566 break;
1567 }
1568 else if (strcmp(args[cur_arg], "odd") == 0) {
1569 set |= 0x55555555;
1570 }
1571 else if (strcmp(args[cur_arg], "even") == 0) {
1572 set |= 0xAAAAAAAA;
1573 }
1574 else {
1575 u = str2uic(args[cur_arg]);
1576 if (u < 1 || u > 32) {
1577 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1578 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001579 err_code |= ERR_ALERT | ERR_FATAL;
1580 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001581 }
1582 if (u > global.nbproc) {
1583 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001586 }
1587 set |= 1 << (u - 1);
1588 }
1589 cur_arg++;
1590 }
1591 curproxy->bind_proc = set;
1592 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001593 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001594 if (curproxy == &defproxy) {
1595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001598 }
1599
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001600 err = invalid_char(args[1]);
1601 if (err) {
1602 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1603 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001605 }
1606
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1608 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1609 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001612 }
1613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1615 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 if (*(args[1]) == 0) {
1621 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001627 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001628 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 curproxy->cookie_name = strdup(args[1]);
1630 curproxy->cookie_len = strlen(curproxy->cookie_name);
1631
1632 cur_arg = 2;
1633 while (*(args[cur_arg])) {
1634 if (!strcmp(args[cur_arg], "rewrite")) {
1635 curproxy->options |= PR_O_COOK_RW;
1636 }
1637 else if (!strcmp(args[cur_arg], "indirect")) {
1638 curproxy->options |= PR_O_COOK_IND;
1639 }
1640 else if (!strcmp(args[cur_arg], "insert")) {
1641 curproxy->options |= PR_O_COOK_INS;
1642 }
1643 else if (!strcmp(args[cur_arg], "nocache")) {
1644 curproxy->options |= PR_O_COOK_NOC;
1645 }
1646 else if (!strcmp(args[cur_arg], "postonly")) {
1647 curproxy->options |= PR_O_COOK_POST;
1648 }
1649 else if (!strcmp(args[cur_arg], "prefix")) {
1650 curproxy->options |= PR_O_COOK_PFX;
1651 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001652 else if (!strcmp(args[cur_arg], "domain")) {
1653 if (!*args[cur_arg + 1]) {
1654 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1655 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001658 }
1659
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001660 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001661 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001662 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1663 " dots nor does not start with a dot."
1664 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001665 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001666 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001667 }
1668
1669 err = invalid_domainchar(args[cur_arg + 1]);
1670 if (err) {
1671 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1672 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
1674 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 }
1676
Willy Tarreau68a897b2009-12-03 23:28:34 +01001677 if (!curproxy->cookie_domain) {
1678 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1679 } else {
1680 /* one domain was already specified, add another one by
1681 * building the string which will be returned along with
1682 * the cookie.
1683 */
1684 char *new_ptr;
1685 int new_len = strlen(curproxy->cookie_domain) +
1686 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1687 new_ptr = malloc(new_len);
1688 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1689 free(curproxy->cookie_domain);
1690 curproxy->cookie_domain = new_ptr;
1691 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001692 cur_arg++;
1693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001695 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
1700 cur_arg++;
1701 }
1702 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1703 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 }
1707
1708 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1709 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1710 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001714 else if (!strcmp(args[0], "persist")) { /* persist */
1715 if (*(args[1]) == 0) {
1716 Alert("parsing [%s:%d] : missing persist method.\n",
1717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001720 }
1721
1722 if (!strncmp(args[1], "rdp-cookie", 10)) {
1723 curproxy->options2 |= PR_O2_RDPC_PRST;
1724
Emeric Brunb982a3d2010-01-04 15:45:53 +01001725 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001726 const char *beg, *end;
1727
1728 beg = args[1] + 11;
1729 end = strchr(beg, ')');
1730
1731 if (!end || end == beg) {
1732 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1733 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001736 }
1737
1738 free(curproxy->rdp_cookie_name);
1739 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1740 curproxy->rdp_cookie_len = end-beg;
1741 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001742 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001743 free(curproxy->rdp_cookie_name);
1744 curproxy->rdp_cookie_name = strdup("msts");
1745 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1746 }
1747 else { /* syntax */
1748 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1749 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001752 }
1753 }
1754 else {
1755 Alert("parsing [%s:%d] : unknown persist method.\n",
1756 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001759 }
1760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001762 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001764 if (curproxy == &defproxy) {
1765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768 }
1769
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001774 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001780 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 curproxy->appsession_name = strdup(args[1]);
1782 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1783 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001784 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1785 if (err) {
1786 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1787 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001790 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001791 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001792
Willy Tarreau51041c72007-09-09 21:56:53 +02001793 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1794 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_ABORT;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001798
1799 cur_arg = 6;
1800 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001801 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1802 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001803 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001804 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001805 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001806 } else if (!strcmp(args[cur_arg], "prefix")) {
1807 curproxy->options2 |= PR_O2_AS_PFX;
1808 } else if (!strcmp(args[cur_arg], "mode")) {
1809 if (!*args[cur_arg + 1]) {
1810 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1811 file, linenum, args[0], args[cur_arg]);
1812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
1815
1816 cur_arg++;
1817 if (!strcmp(args[cur_arg], "query-string")) {
1818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1819 curproxy->options2 |= PR_O2_AS_M_QS;
1820 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1821 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1822 curproxy->options2 |= PR_O2_AS_M_PP;
1823 } else {
1824 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
1828 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001829 cur_arg++;
1830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001831 } /* Url App Session */
1832 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001833 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001837 if (curproxy == &defproxy) {
1838 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 if (*(args[4]) == 0) {
1844 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001849 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 curproxy->capture_name = strdup(args[2]);
1851 curproxy->capture_namelen = strlen(curproxy->capture_name);
1852 curproxy->capture_len = atol(args[4]);
1853 if (curproxy->capture_len >= CAPTURE_LEN) {
1854 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1855 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 curproxy->capture_len = CAPTURE_LEN - 1;
1858 }
1859 curproxy->to_log |= LW_COOKIE;
1860 }
1861 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1862 struct cap_hdr *hdr;
1863
1864 if (curproxy == &defproxy) {
1865 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 }
1869
1870 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1871 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1872 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 }
1876
1877 hdr = calloc(sizeof(struct cap_hdr), 1);
1878 hdr->next = curproxy->req_cap;
1879 hdr->name = strdup(args[3]);
1880 hdr->namelen = strlen(args[3]);
1881 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001882 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 hdr->index = curproxy->nb_req_cap++;
1884 curproxy->req_cap = hdr;
1885 curproxy->to_log |= LW_REQHDR;
1886 }
1887 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1888 struct cap_hdr *hdr;
1889
1890 if (curproxy == &defproxy) {
1891 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
1895
1896 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1897 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1898 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
1902 hdr = calloc(sizeof(struct cap_hdr), 1);
1903 hdr->next = curproxy->rsp_cap;
1904 hdr->name = strdup(args[3]);
1905 hdr->namelen = strlen(args[3]);
1906 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001907 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 hdr->index = curproxy->nb_rsp_cap++;
1909 curproxy->rsp_cap = hdr;
1910 curproxy->to_log |= LW_RSPHDR;
1911 }
1912 else {
1913 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 }
1918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 if (*(args[1]) == 0) {
1924 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
1929 curproxy->conn_retries = atol(args[1]);
1930 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001931 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1932 struct req_acl_rule *req_acl;
1933
1934 if (curproxy == &defproxy) {
1935 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940
1941 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1942 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1943 file, linenum, args[0]);
1944 err_code |= ERR_WARN;
1945 }
1946
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001947 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001948
1949 if (!req_acl) {
1950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
1952 }
1953
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001954 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001955 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1956 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001957 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001958 if (curproxy == &defproxy) {
1959 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001962 }
1963
Willy Tarreauef6494c2010-01-28 17:12:36 +01001964 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001965 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001969 }
1970
Willy Tarreauef6494c2010-01-28 17:12:36 +01001971 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001972 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1973 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001976 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001977
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001978 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001979 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001980 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001981 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001982 struct redirect_rule *rule;
1983 int cur_arg;
1984 int type = REDIRECT_TYPE_NONE;
1985 int code = 302;
1986 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001987 char *cookie = NULL;
1988 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001989 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001990
Cyril Bonté99ed3272010-01-24 23:29:44 +01001991 if (curproxy == &defproxy) {
1992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
1995 }
1996
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001997 cur_arg = 1;
1998 while (*(args[cur_arg])) {
1999 if (!strcmp(args[cur_arg], "location")) {
2000 if (!*args[cur_arg + 1]) {
2001 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2002 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002005 }
2006
2007 type = REDIRECT_TYPE_LOCATION;
2008 cur_arg++;
2009 destination = args[cur_arg];
2010 }
2011 else if (!strcmp(args[cur_arg], "prefix")) {
2012 if (!*args[cur_arg + 1]) {
2013 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2014 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002017 }
2018
2019 type = REDIRECT_TYPE_PREFIX;
2020 cur_arg++;
2021 destination = args[cur_arg];
2022 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002023 else if (!strcmp(args[cur_arg], "set-cookie")) {
2024 if (!*args[cur_arg + 1]) {
2025 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2026 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002029 }
2030
2031 cur_arg++;
2032 cookie = args[cur_arg];
2033 cookie_set = 1;
2034 }
2035 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2036 if (!*args[cur_arg + 1]) {
2037 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2038 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002041 }
2042
2043 cur_arg++;
2044 cookie = args[cur_arg];
2045 cookie_set = 0;
2046 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002047 else if (!strcmp(args[cur_arg],"code")) {
2048 if (!*args[cur_arg + 1]) {
2049 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002053 }
2054 cur_arg++;
2055 code = atol(args[cur_arg]);
2056 if (code < 301 || code > 303) {
2057 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2058 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002061 }
2062 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002063 else if (!strcmp(args[cur_arg],"drop-query")) {
2064 flags |= REDIRECT_FLAG_DROP_QS;
2065 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002066 else if (!strcmp(args[cur_arg],"append-slash")) {
2067 flags |= REDIRECT_FLAG_APPEND_SLASH;
2068 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002069 else if (strcmp(args[cur_arg], "if") == 0 ||
2070 strcmp(args[cur_arg], "unless") == 0) {
2071 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2072 if (!cond) {
2073 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2074 file, linenum, args[0]);
2075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
2077 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002078 break;
2079 }
2080 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002081 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 +02002082 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002085 }
2086 cur_arg++;
2087 }
2088
2089 if (type == REDIRECT_TYPE_NONE) {
2090 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002094 }
2095
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002096 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2097 rule->cond = cond;
2098 rule->rdr_str = strdup(destination);
2099 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002100 if (cookie) {
2101 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2102 * a clear consists in appending "; Max-Age=0" at the end.
2103 */
2104 rule->cookie_len = strlen(cookie);
2105 if (cookie_set)
2106 rule->cookie_str = strdup(cookie);
2107 else {
2108 rule->cookie_str = malloc(rule->cookie_len + 12);
2109 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2110 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2111 rule->cookie_len += 11;
2112 }
2113 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002114 rule->type = type;
2115 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002116 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002117 LIST_INIT(&rule->list);
2118 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002119 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002120 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002121 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002122 struct switching_rule *rule;
2123
Willy Tarreaub099aca2008-10-12 17:26:37 +02002124 if (curproxy == &defproxy) {
2125 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002128 }
2129
Willy Tarreau55ea7572007-06-17 19:56:27 +02002130 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002132
2133 if (*(args[1]) == 0) {
2134 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002137 }
2138
Willy Tarreauef6494c2010-01-28 17:12:36 +01002139 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002140 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002144 }
2145
Willy Tarreauef6494c2010-01-28 17:12:36 +01002146 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002147 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002148 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002151 }
2152
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002153 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002154
Willy Tarreau55ea7572007-06-17 19:56:27 +02002155 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2156 rule->cond = cond;
2157 rule->be.name = strdup(args[1]);
2158 LIST_INIT(&rule->list);
2159 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2160 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002161 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002162 struct force_persist_rule *rule;
2163
2164 if (curproxy == &defproxy) {
2165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169
2170 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2171 err_code |= ERR_WARN;
2172
Willy Tarreauef6494c2010-01-28 17:12:36 +01002173 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002174 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2175 file, linenum, args[0]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
Willy Tarreauef6494c2010-01-28 17:12:36 +01002180 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002181 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2182 file, linenum);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002187 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002188
2189 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2190 rule->cond = cond;
2191 LIST_INIT(&rule->list);
2192 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002194 else if (!strcmp(args[0], "stick-table")) {
2195 int myidx = 1;
2196
2197 curproxy->table.type = (unsigned int)-1;
2198 while (*args[myidx]) {
2199 const char *err;
2200
2201 if (strcmp(args[myidx], "size") == 0) {
2202 myidx++;
2203 if (!*(args[myidx])) {
2204 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2205 file, linenum, args[myidx-1]);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2210 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2211 file, linenum, *err, args[myidx-1]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002215 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002216 }
2217 else if (strcmp(args[myidx], "expire") == 0) {
2218 myidx++;
2219 if (!*(args[myidx])) {
2220 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2221 file, linenum, args[myidx-1]);
2222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
2224 }
2225 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2226 if (err) {
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 }
2232 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002233 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002234 }
2235 else if (strcmp(args[myidx], "nopurge") == 0) {
2236 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002237 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002238 }
2239 else if (strcmp(args[myidx], "type") == 0) {
2240 myidx++;
2241 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2242 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2243 file, linenum, args[myidx]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002247 /* myidx already points to next arg */
2248 }
2249 else {
2250 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2251 file, linenum, args[myidx]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002254 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002255 }
2256
2257 if (!curproxy->table.size) {
2258 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2259 file, linenum);
2260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
2262 }
2263
2264 if (curproxy->table.type == (unsigned int)-1) {
2265 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2266 file, linenum);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270 }
2271 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002272 struct sticking_rule *rule;
2273 struct pattern_expr *expr;
2274 int myidx = 0;
2275 const char *name = NULL;
2276 int flags;
2277
2278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2285 err_code |= ERR_WARN;
2286 goto out;
2287 }
2288
2289 myidx++;
2290 if ((strcmp(args[myidx], "store") == 0) ||
2291 (strcmp(args[myidx], "store-request") == 0)) {
2292 myidx++;
2293 flags = STK_IS_STORE;
2294 }
2295 else if (strcmp(args[myidx], "store-response") == 0) {
2296 myidx++;
2297 flags = STK_IS_STORE | STK_ON_RSP;
2298 }
2299 else if (strcmp(args[myidx], "match") == 0) {
2300 myidx++;
2301 flags = STK_IS_MATCH;
2302 }
2303 else if (strcmp(args[myidx], "on") == 0) {
2304 myidx++;
2305 flags = STK_IS_MATCH | STK_IS_STORE;
2306 }
2307 else {
2308 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
2313 if (*(args[myidx]) == 0) {
2314 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 expr = pattern_parse_expr(args, &myidx);
2320 if (!expr) {
2321 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325
2326 if (flags & STK_ON_RSP) {
2327 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2328 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2329 file, linenum, args[0], expr->fetch->kw);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 } else {
2334 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2335 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2336 file, linenum, args[0], expr->fetch->kw);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 }
2341
2342 if (strcmp(args[myidx], "table") == 0) {
2343 myidx++;
2344 name = args[myidx++];
2345 }
2346
Willy Tarreauef6494c2010-01-28 17:12:36 +01002347 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2348 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002349 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2350 file, linenum, args[0]);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002354 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002355 else if (*(args[myidx])) {
2356 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2357 file, linenum, args[0], args[myidx]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002362 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2363
Emeric Brunb982a3d2010-01-04 15:45:53 +01002364 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2365 rule->cond = cond;
2366 rule->expr = expr;
2367 rule->flags = flags;
2368 rule->table.name = name ? strdup(name) : NULL;
2369 LIST_INIT(&rule->list);
2370 if (flags & STK_ON_RSP)
2371 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2372 else
2373 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2380 curproxy->uri_auth = NULL; /* we must detach from the default config */
2381
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002382 if (!*args[1]) {
2383 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 } else if (!strcmp(args[1], "uri")) {
2385 if (*(args[2]) == 0) {
2386 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 } else if (!strcmp(args[1], "realm")) {
2395 if (*(args[2]) == 0) {
2396 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002404 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002405 unsigned interval;
2406
2407 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2408 if (err) {
2409 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2410 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002413 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_ABORT;
2416 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002417 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002418 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2419 struct req_acl_rule *req_acl;
2420
2421 if (curproxy == &defproxy) {
2422 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2428 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2429 err_code |= ERR_ALERT | ERR_ABORT;
2430 goto out;
2431 }
2432
2433 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2434 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2435 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2436 file, linenum, args[0]);
2437 err_code |= ERR_WARN;
2438 }
2439
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002440 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002441
2442 if (!req_acl) {
2443 err_code |= ERR_ALERT | ERR_ABORT;
2444 goto out;
2445 }
2446
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002447 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002448 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2449
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 } else if (!strcmp(args[1], "auth")) {
2451 if (*(args[2]) == 0) {
2452 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2456 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_ABORT;
2458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
2460 } else if (!strcmp(args[1], "scope")) {
2461 if (*(args[2]) == 0) {
2462 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2466 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_ABORT;
2468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 } else if (!strcmp(args[1], "enable")) {
2471 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2472 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_ABORT;
2474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002476 } else if (!strcmp(args[1], "hide-version")) {
2477 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2478 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_ABORT;
2480 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002481 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002482 } else if (!strcmp(args[1], "show-legends")) {
2483 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2485 err_code |= ERR_ALERT | ERR_ABORT;
2486 goto out;
2487 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002488 } else if (!strcmp(args[1], "show-node")) {
2489
2490 if (*args[2]) {
2491 int i;
2492 char c;
2493
2494 for (i=0; args[2][i]; i++) {
2495 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002496 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002497 break;
2498 }
2499
2500 if (!i || args[2][i]) {
2501 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2502 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2503 file, linenum, args[0], args[1]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507 }
2508
2509 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2510 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2511 err_code |= ERR_ALERT | ERR_ABORT;
2512 goto out;
2513 }
2514 } else if (!strcmp(args[1], "show-desc")) {
2515 char *desc = NULL;
2516
2517 if (*args[2]) {
2518 int i, len=0;
2519 char *d;
2520
2521 for(i=2; *args[i]; i++)
2522 len += strlen(args[i])+1;
2523
2524 desc = d = (char *)calloc(1, len);
2525
2526 d += sprintf(d, "%s", args[2]);
2527 for(i=3; *args[i]; i++)
2528 d += sprintf(d, " %s", args[i]);
2529 }
2530
2531 if (!*args[2] && !global.desc)
2532 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2533 file, linenum, args[1]);
2534 else {
2535 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2536 free(desc);
2537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2538 err_code |= ERR_ALERT | ERR_ABORT;
2539 goto out;
2540 }
2541 free(desc);
2542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002544stats_error_parsing:
2545 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2546 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550 }
2551 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002552 int optnum;
2553
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002554 if (*(args[1]) == '\0') {
2555 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002560
2561 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2562 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002563 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2564 err_code |= ERR_WARN;
2565 goto out;
2566 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002567
Willy Tarreau3842f002009-06-14 11:39:52 +02002568 curproxy->no_options &= ~cfg_opts[optnum].val;
2569 curproxy->options &= ~cfg_opts[optnum].val;
2570
2571 switch (kwm) {
2572 case KWM_STD:
2573 curproxy->options |= cfg_opts[optnum].val;
2574 break;
2575 case KWM_NO:
2576 curproxy->no_options |= cfg_opts[optnum].val;
2577 break;
2578 case KWM_DEF: /* already cleared */
2579 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002580 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002581
Willy Tarreau93893792009-07-23 13:19:11 +02002582 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002583 }
2584 }
2585
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002586 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2587 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002588 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2589 err_code |= ERR_WARN;
2590 goto out;
2591 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002592
Willy Tarreau3842f002009-06-14 11:39:52 +02002593 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2594 curproxy->options2 &= ~cfg_opts2[optnum].val;
2595
2596 switch (kwm) {
2597 case KWM_STD:
2598 curproxy->options2 |= cfg_opts2[optnum].val;
2599 break;
2600 case KWM_NO:
2601 curproxy->no_options2 |= cfg_opts2[optnum].val;
2602 break;
2603 case KWM_DEF: /* already cleared */
2604 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002605 }
Willy Tarreau93893792009-07-23 13:19:11 +02002606 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002607 }
2608 }
2609
Willy Tarreau3842f002009-06-14 11:39:52 +02002610 if (kwm != KWM_STD) {
2611 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002612 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002615 }
2616
Emeric Brun3a058f32009-06-30 18:26:00 +02002617 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002619 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002620 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002621 if (*(args[2]) != '\0') {
2622 if (!strcmp(args[2], "clf")) {
2623 curproxy->options2 |= PR_O2_CLFLOG;
2624 } else {
2625 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002628 }
2629 }
2630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 else if (!strcmp(args[1], "tcplog"))
2632 /* generate a detailed TCP log */
2633 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 else if (!strcmp(args[1], "tcpka")) {
2635 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002636 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002638
2639 if (curproxy->cap & PR_CAP_FE)
2640 curproxy->options |= PR_O_TCP_CLI_KA;
2641 if (curproxy->cap & PR_CAP_BE)
2642 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002645 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_WARN;
2647
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002649 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002650 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002651 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002652 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002653 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002654 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 if (!*args[2]) { /* no argument */
2656 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2657 curproxy->check_len = strlen(DEF_CHECK_REQ);
2658 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002659 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 curproxy->check_req = (char *)malloc(reqlen);
2661 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002662 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002664 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 if (*args[4])
2666 reqlen += strlen(args[4]);
2667 else
2668 reqlen += strlen("HTTP/1.0");
2669
2670 curproxy->check_req = (char *)malloc(reqlen);
2671 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002672 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002674 }
2675 else if (!strcmp(args[1], "ssl-hello-chk")) {
2676 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002677 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002679
Willy Tarreaua534fea2008-08-03 12:19:50 +02002680 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002681 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002682 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002683 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002684 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002685 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 }
Willy Tarreau23677902007-05-08 23:50:35 +02002687 else if (!strcmp(args[1], "smtpchk")) {
2688 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002689 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002690 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002691 curproxy->options &= ~PR_O_HTTP_CHK;
2692 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002693 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002694 curproxy->options |= PR_O_SMTP_CHK;
2695
2696 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2697 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2698 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2699 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2700 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2701 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2702 curproxy->check_req = (char *)malloc(reqlen);
2703 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2704 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2705 } else {
2706 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2707 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2708 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2709 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2710 }
2711 }
2712 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002713 else if (!strcmp(args[1], "mysql-check")) {
2714 /* use MYSQL request to check servers' health */
2715 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002716 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002717 curproxy->options &= ~PR_O_HTTP_CHK;
2718 curproxy->options &= ~PR_O_SSL3_CHK;
2719 curproxy->options &= ~PR_O_SMTP_CHK;
2720 curproxy->options2 |= PR_O2_MYSQL_CHK;
2721 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002722 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002723 int cur_arg;
2724
2725 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2726 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002727 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002728
2729 curproxy->options |= PR_O_FWDFOR;
2730
2731 free(curproxy->fwdfor_hdr_name);
2732 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2733 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2734
2735 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2736 cur_arg = 2;
2737 while (*(args[cur_arg])) {
2738 if (!strcmp(args[cur_arg], "except")) {
2739 /* suboption except - needs additional argument for it */
2740 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2741 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2742 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002745 }
2746 /* flush useless bits */
2747 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002748 cur_arg += 2;
2749 } else if (!strcmp(args[cur_arg], "header")) {
2750 /* suboption header - needs additional argument for it */
2751 if (*(args[cur_arg+1]) == 0) {
2752 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2753 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002756 }
2757 free(curproxy->fwdfor_hdr_name);
2758 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2759 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2760 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002761 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002762 /* unknown suboption - catchall */
2763 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2764 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002767 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002768 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002769 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002770 else if (!strcmp(args[1], "originalto")) {
2771 int cur_arg;
2772
2773 /* insert x-original-to field, but not for the IP address listed as an except.
2774 * set default options (ie: bitfield, header name, etc)
2775 */
2776
2777 curproxy->options |= PR_O_ORGTO;
2778
2779 free(curproxy->orgto_hdr_name);
2780 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2781 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2782
2783 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2784 cur_arg = 2;
2785 while (*(args[cur_arg])) {
2786 if (!strcmp(args[cur_arg], "except")) {
2787 /* suboption except - needs additional argument for it */
2788 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2789 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2790 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002793 }
2794 /* flush useless bits */
2795 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2796 cur_arg += 2;
2797 } else if (!strcmp(args[cur_arg], "header")) {
2798 /* suboption header - needs additional argument for it */
2799 if (*(args[cur_arg+1]) == 0) {
2800 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2801 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002804 }
2805 free(curproxy->orgto_hdr_name);
2806 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2807 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2808 cur_arg += 2;
2809 } else {
2810 /* unknown suboption - catchall */
2811 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2812 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002815 }
2816 } /* end while loop */
2817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 else {
2819 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 }
Willy Tarreau93893792009-07-23 13:19:11 +02002823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002825 else if (!strcmp(args[0], "default_backend")) {
2826 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002828
2829 if (*(args[1]) == 0) {
2830 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002833 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002834 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002835 curproxy->defbe.name = strdup(args[1]);
2836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002840
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002841 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 /* enable reconnections to dispatch */
2845 curproxy->options |= PR_O_REDISP;
2846 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002847 else if (!strcmp(args[0], "http-check")) {
2848 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002850
2851 if (strcmp(args[1], "disable-on-404") == 0) {
2852 /* enable a graceful server shutdown on an HTTP 404 response */
2853 curproxy->options |= PR_O_DISABLE404;
2854 }
Willy Tarreauef781042010-01-27 11:53:01 +01002855 else if (strcmp(args[1], "send-state") == 0) {
2856 /* enable emission of the apparent state of a server in HTTP checks */
2857 curproxy->options2 |= PR_O2_CHK_SNDST;
2858 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002859 else {
2860 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002863 }
2864 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002865 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002866 if (curproxy == &defproxy) {
2867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002870 }
2871
Willy Tarreaub80c2302007-11-30 20:51:32 +01002872 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002874
2875 if (strcmp(args[1], "fail") == 0) {
2876 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002877 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002878 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2879 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002882 }
2883
Willy Tarreauef6494c2010-01-28 17:12:36 +01002884 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002885 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2886 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002889 }
2890 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2891 }
2892 else {
2893 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002896 }
2897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898#ifdef TPROXY
2899 else if (!strcmp(args[0], "transparent")) {
2900 /* enable transparent proxy connections */
2901 curproxy->options |= PR_O_TRANSP;
2902 }
2903#endif
2904 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002905 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 if (*(args[1]) == 0) {
2909 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
2913 curproxy->maxconn = atol(args[1]);
2914 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002915 else if (!strcmp(args[0], "backlog")) { /* backlog */
2916 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002918
2919 if (*(args[1]) == 0) {
2920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002923 }
2924 curproxy->backlog = atol(args[1]);
2925 }
Willy Tarreau86034312006-12-29 00:10:33 +01002926 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002929
Willy Tarreau86034312006-12-29 00:10:33 +01002930 if (*(args[1]) == 0) {
2931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002932 err_code |= ERR_ALERT | ERR_FATAL;
2933 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002934 }
2935 curproxy->fullconn = atol(args[1]);
2936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002943 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2944 if (err) {
2945 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2946 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002949 }
2950 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 }
2952 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2953 if (curproxy == &defproxy) {
2954 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002958 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002960
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 if (strchr(args[1], ':') == NULL) {
2962 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
2966 curproxy->dispatch_addr = *str2sa(args[1]);
2967 }
2968 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002971
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002972 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002973 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2974 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002978 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002979 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2981 err_code |= ERR_WARN;
2982
2983 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2984 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2985 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2986 }
2987 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2988 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2989 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2990 }
2991 else {
2992 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002997 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002999 char *rport, *raddr;
3000 short realport = 0;
3001 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003003 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010
3011 if (!*args[2]) {
3012 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003017
3018 err = invalid_char(args[1]);
3019 if (err) {
3020 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3021 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003024 }
3025
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003026 if (!defsrv) {
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003027 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3028 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3029 err_code |= ERR_ALERT | ERR_ABORT;
3030 goto out;
3031 }
3032
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003033 /* the servers are linked backwards first */
3034 newsrv->next = curproxy->srv;
3035 curproxy->srv = newsrv;
3036 newsrv->proxy = curproxy;
3037 newsrv->conf.file = file;
3038 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003040 LIST_INIT(&newsrv->pendconns);
3041 do_check = 0;
3042 newsrv->state = SRV_RUNNING; /* early server setup */
3043 newsrv->last_change = now.tv_sec;
3044 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003046 /* several ways to check the port component :
3047 * - IP => port=+0, relative
3048 * - IP: => port=+0, relative
3049 * - IP:N => port=N, absolute
3050 * - IP:+N => port=+N, relative
3051 * - IP:-N => port=-N, relative
3052 */
3053 raddr = strdup(args[2]);
3054 rport = strchr(raddr, ':');
3055 if (rport) {
3056 *rport++ = 0;
3057 realport = atol(rport);
3058 if (!isdigit((unsigned char)*rport))
3059 newsrv->state |= SRV_MAPPORTS;
3060 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003062
3063 newsrv->addr = *str2sa(raddr);
3064 newsrv->addr.sin_port = htons(realport);
3065 free(raddr);
3066
3067 newsrv->check_port = curproxy->defsrv.check_port;
3068 newsrv->inter = curproxy->defsrv.inter;
3069 newsrv->fastinter = curproxy->defsrv.fastinter;
3070 newsrv->downinter = curproxy->defsrv.downinter;
3071 newsrv->rise = curproxy->defsrv.rise;
3072 newsrv->fall = curproxy->defsrv.fall;
3073 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3074 newsrv->minconn = curproxy->defsrv.minconn;
3075 newsrv->maxconn = curproxy->defsrv.maxconn;
3076 newsrv->slowstart = curproxy->defsrv.slowstart;
3077 newsrv->onerror = curproxy->defsrv.onerror;
3078 newsrv->consecutive_errors_limit
3079 = curproxy->defsrv.consecutive_errors_limit;
3080 newsrv->uweight = newsrv->iweight
3081 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003083 newsrv->curfd = -1; /* no health-check in progress */
3084 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003086 cur_arg = 3;
3087 } else {
3088 newsrv = &curproxy->defsrv;
3089 cur_arg = 1;
3090 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003091
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003093 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003094 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003095
3096 if (!*args[cur_arg + 1]) {
3097 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3098 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003101 }
3102
3103 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003104 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003105
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003106 if (newsrv->puid <= 0) {
3107 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003108 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003111 }
3112
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003113 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3114 if (node) {
3115 struct server *target = container_of(node, struct server, conf.id);
3116 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3117 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003122 cur_arg += 2;
3123 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003124 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 newsrv->cookie = strdup(args[cur_arg + 1]);
3126 newsrv->cklen = strlen(args[cur_arg + 1]);
3127 cur_arg += 2;
3128 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003129 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003130 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3131 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3132 cur_arg += 2;
3133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003135 if (!*args[cur_arg + 1]) {
3136 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3137 file, linenum, args[cur_arg]);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140 }
3141
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003143 if (newsrv->rise <= 0) {
3144 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3145 file, linenum, args[cur_arg]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 newsrv->health = newsrv->rise;
3151 cur_arg += 2;
3152 }
3153 else if (!strcmp(args[cur_arg], "fall")) {
3154 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003155
3156 if (!*args[cur_arg + 1]) {
3157 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3158 file, linenum, args[cur_arg]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
3161 }
3162
3163 if (newsrv->fall <= 0) {
3164 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3165 file, linenum, args[cur_arg]);
3166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
3168 }
3169
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 cur_arg += 2;
3171 }
3172 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003173 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3174 if (err) {
3175 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3176 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003179 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003180 if (val <= 0) {
3181 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3182 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003185 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003186 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 cur_arg += 2;
3188 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003189 else if (!strcmp(args[cur_arg], "fastinter")) {
3190 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3191 if (err) {
3192 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3193 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003196 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003197 if (val <= 0) {
3198 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3199 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003202 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003203 newsrv->fastinter = val;
3204 cur_arg += 2;
3205 }
3206 else if (!strcmp(args[cur_arg], "downinter")) {
3207 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3208 if (err) {
3209 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3210 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003213 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003214 if (val <= 0) {
3215 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3216 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003219 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003220 newsrv->downinter = val;
3221 cur_arg += 2;
3222 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003223 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003224 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003225 cur_arg += 2;
3226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 else if (!strcmp(args[cur_arg], "port")) {
3228 newsrv->check_port = atol(args[cur_arg + 1]);
3229 cur_arg += 2;
3230 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003231 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 newsrv->state |= SRV_BACKUP;
3233 cur_arg ++;
3234 }
3235 else if (!strcmp(args[cur_arg], "weight")) {
3236 int w;
3237 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003238 if (w < 0 || w > 256) {
3239 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003244 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 cur_arg += 2;
3246 }
3247 else if (!strcmp(args[cur_arg], "minconn")) {
3248 newsrv->minconn = atol(args[cur_arg + 1]);
3249 cur_arg += 2;
3250 }
3251 else if (!strcmp(args[cur_arg], "maxconn")) {
3252 newsrv->maxconn = atol(args[cur_arg + 1]);
3253 cur_arg += 2;
3254 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003255 else if (!strcmp(args[cur_arg], "maxqueue")) {
3256 newsrv->maxqueue = atol(args[cur_arg + 1]);
3257 cur_arg += 2;
3258 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003259 else if (!strcmp(args[cur_arg], "slowstart")) {
3260 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003261 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003262 if (err) {
3263 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3264 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003267 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003268 if (val <= 0) {
3269 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3270 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003273 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003274 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003275 cur_arg += 2;
3276 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003277 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003278
3279 if (!*args[cur_arg + 1]) {
3280 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003284 }
3285
3286 newsrv->trackit = strdup(args[cur_arg + 1]);
3287
3288 cur_arg += 2;
3289 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003290 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 global.maxsock++;
3292 do_check = 1;
3293 cur_arg += 1;
3294 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003295 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003296 if (!strcmp(args[cur_arg + 1], "none"))
3297 newsrv->observe = HANA_OBS_NONE;
3298 else if (!strcmp(args[cur_arg + 1], "layer4"))
3299 newsrv->observe = HANA_OBS_LAYER4;
3300 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3301 if (curproxy->mode != PR_MODE_HTTP) {
3302 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3303 file, linenum, args[cur_arg + 1]);
3304 err_code |= ERR_ALERT;
3305 }
3306 newsrv->observe = HANA_OBS_LAYER7;
3307 }
3308 else {
3309 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3310 "'l4events', 'http-responses' but get '%s'\n",
3311 file, linenum, args[cur_arg], args[cur_arg + 1]);
3312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
3315
3316 cur_arg += 2;
3317 }
3318 else if (!strcmp(args[cur_arg], "on-error")) {
3319 if (!strcmp(args[cur_arg + 1], "fastinter"))
3320 newsrv->onerror = HANA_ONERR_FASTINTER;
3321 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3322 newsrv->onerror = HANA_ONERR_FAILCHK;
3323 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3324 newsrv->onerror = HANA_ONERR_SUDDTH;
3325 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3326 newsrv->onerror = HANA_ONERR_MARKDWN;
3327 else {
3328 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3329 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3330 file, linenum, args[cur_arg], args[cur_arg + 1]);
3331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
3333 }
3334
3335 cur_arg += 2;
3336 }
3337 else if (!strcmp(args[cur_arg], "error-limit")) {
3338 if (!*args[cur_arg + 1]) {
3339 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3340 file, linenum, args[cur_arg]);
3341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
3343 }
3344
3345 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3346
3347 if (newsrv->consecutive_errors_limit <= 0) {
3348 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3349 file, linenum, args[cur_arg]);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
3353 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003354 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003355 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003357#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003358 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003359 file, linenum, "source", "usesrc");
3360#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003361 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003363#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003368 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3369
3370 if (port_low != port_high) {
3371 int i;
3372 if (port_low <= 0 || port_low > 65535 ||
3373 port_high <= 0 || port_high > 65535 ||
3374 port_low > port_high) {
3375 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3376 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003379 }
3380 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3381 for (i = 0; i < newsrv->sport_range->size; i++)
3382 newsrv->sport_range->ports[i] = port_low + i;
3383 }
3384
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003386 while (*(args[cur_arg])) {
3387 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003388#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3389#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003390 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3391 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3392 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003395 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003396#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003397 if (!*args[cur_arg + 1]) {
3398 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3399 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003402 }
3403 if (!strcmp(args[cur_arg + 1], "client")) {
3404 newsrv->state |= SRV_TPROXY_CLI;
3405 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3406 newsrv->state |= SRV_TPROXY_CIP;
3407 } else {
3408 newsrv->state |= SRV_TPROXY_ADDR;
3409 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3410 }
3411 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003412#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003413 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003414#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003415 cur_arg += 2;
3416 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003417#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003418 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003419 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003422#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3423 } /* "usesrc" */
3424
3425 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3426#ifdef SO_BINDTODEVICE
3427 if (!*args[cur_arg + 1]) {
3428 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003432 }
3433 if (newsrv->iface_name)
3434 free(newsrv->iface_name);
3435
3436 newsrv->iface_name = strdup(args[cur_arg + 1]);
3437 newsrv->iface_len = strlen(newsrv->iface_name);
3438 global.last_checks |= LSTCHK_NETADM;
3439#else
3440 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3441 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003444#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003445 cur_arg += 2;
3446 continue;
3447 }
3448 /* this keyword in not an option of "source" */
3449 break;
3450 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003452 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003453 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3454 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003459 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003460 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 +01003461 file, linenum, newsrv->id);
3462 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003463 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 +01003464 file, linenum);
3465
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 }
3469 }
3470
3471 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003472 if (newsrv->trackit) {
3473 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003477 }
3478
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003479 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3480 newsrv->check_port = newsrv->check_addr.sin_port;
3481
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3483 newsrv->check_port = realport; /* by default */
3484 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003485 /* not yet valid, because no port was set on
3486 * the server either. We'll check if we have
3487 * a known port on the first listener.
3488 */
3489 struct listener *l;
3490 l = curproxy->listen;
3491 if (l) {
3492 int port;
3493 port = (l->addr.ss_family == AF_INET6)
3494 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3495 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3496 newsrv->check_port = port;
3497 }
3498 }
3499 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3501 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003505
3506 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 newsrv->state |= SRV_CHECKED;
3508 }
3509
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003510 if (!defsrv) {
3511 if (newsrv->state & SRV_BACKUP)
3512 curproxy->srv_bck++;
3513 else
3514 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003515
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003516 newsrv->prev_state = newsrv->state;
3517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003520 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 int facility;
3522
3523 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3524 curproxy->logfac1 = global.logfac1;
3525 curproxy->logsrv1 = global.logsrv1;
3526 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003527 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 curproxy->logfac2 = global.logfac2;
3529 curproxy->logsrv2 = global.logsrv2;
3530 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003531 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
3533 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003534 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535
3536 facility = get_log_facility(args[2]);
3537 if (facility < 0) {
3538 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3539 exit(1);
3540 }
3541
3542 level = 7; /* max syslog level = debug */
3543 if (*(args[3])) {
3544 level = get_log_level(args[3]);
3545 if (level < 0) {
3546 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3547 exit(1);
3548 }
3549 }
3550
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003551 minlvl = 0; /* limit syslog level to this level (emerg) */
3552 if (*(args[4])) {
3553 minlvl = get_log_level(args[4]);
3554 if (level < 0) {
3555 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3556 exit(1);
3557 }
3558 }
3559
Robert Tsai81ae1952007-12-05 10:47:29 +01003560 if (args[1][0] == '/') {
3561 logsrv.u.addr.sa_family = AF_UNIX;
3562 logsrv.u.un = *str2sun(args[1]);
3563 } else {
3564 logsrv.u.addr.sa_family = AF_INET;
3565 logsrv.u.in = *str2sa(args[1]);
3566 if (!logsrv.u.in.sin_port) {
3567 logsrv.u.in.sin_port =
3568 htons(SYSLOG_PORT);
3569 }
3570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571
3572 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003573 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 curproxy->logfac1 = facility;
3575 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003576 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
3578 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003579 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 curproxy->logfac2 = facility;
3581 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003582 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
3584 else {
3585 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
3589 }
3590 else {
3591 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 }
3596 }
3597 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003598 int cur_arg;
3599
Willy Tarreau977b8e42006-12-29 14:19:17 +01003600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003602
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003604 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3605 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003609
3610 /* we must first clear any optional default setting */
3611 curproxy->options &= ~PR_O_TPXY_MASK;
3612 free(curproxy->iface_name);
3613 curproxy->iface_name = NULL;
3614 curproxy->iface_len = 0;
3615
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 curproxy->source_addr = *str2sa(args[1]);
3617 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003618
3619 cur_arg = 2;
3620 while (*(args[cur_arg])) {
3621 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003622#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3623#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003624 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3625 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3626 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003629 }
3630#endif
3631 if (!*args[cur_arg + 1]) {
3632 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3633 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003636 }
3637
3638 if (!strcmp(args[cur_arg + 1], "client")) {
3639 curproxy->options |= PR_O_TPXY_CLI;
3640 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3641 curproxy->options |= PR_O_TPXY_CIP;
3642 } else {
3643 curproxy->options |= PR_O_TPXY_ADDR;
3644 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3645 }
3646 global.last_checks |= LSTCHK_NETADM;
3647#if !defined(CONFIG_HAP_LINUX_TPROXY)
3648 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003649#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003650#else /* no TPROXY support */
3651 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003652 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003655#endif
3656 cur_arg += 2;
3657 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003658 }
3659
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003660 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3661#ifdef SO_BINDTODEVICE
3662 if (!*args[cur_arg + 1]) {
3663 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3664 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003667 }
3668 if (curproxy->iface_name)
3669 free(curproxy->iface_name);
3670
3671 curproxy->iface_name = strdup(args[cur_arg + 1]);
3672 curproxy->iface_len = strlen(curproxy->iface_name);
3673 global.last_checks |= LSTCHK_NETADM;
3674#else
3675 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3676 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003679#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003680 cur_arg += 2;
3681 continue;
3682 }
3683 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3684 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003689 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3690 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3691 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003696 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003702
3703 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3704 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003705 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003706 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003710 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3711 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003712 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003713 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
3716 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003717 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3718 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003719 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003720 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
3723 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003724 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3725 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003726 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003727 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 }
3730 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003731 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3732 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003733 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003734 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003737 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003738 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3739 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003740 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003741 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003742 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003743 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003744 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003745 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3746 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003747 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003748 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003749 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003750 }
3751 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3753 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003754 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003756 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003759 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003765
3766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3767 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003768 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
3772 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3774 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3781 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003785 }
3786 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3788 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 }
3793 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3795 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003796 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003800 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3802 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003805 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003808 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003809
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 if (curproxy == &defproxy) {
3811 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003815 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003823
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003824 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3825 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3826 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3827 file, linenum, args[0]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3832 }
3833 else if (*args[2]) {
3834 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3835 file, linenum, args[0], args[2]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003840 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003841 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003842 wl->s = strdup(args[1]);
3843 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003844 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 }
3846 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003847 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3849 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003853
Willy Tarreauade5ec42010-01-28 19:33:49 +01003854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3855 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003856 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
3860 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3862 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3869 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
3874 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003875 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3877 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
3881
Willy Tarreauade5ec42010-01-28 19:33:49 +01003882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3883 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003884 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003885 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
3888 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003889 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3890 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003891 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003892 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
3895 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003896 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3897 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003898 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003899 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 }
3902 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003903 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003904
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 if (curproxy == &defproxy) {
3906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003910 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003912
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 if (*(args[1]) == 0) {
3914 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 }
3918
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003919 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3920 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3921 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3922 file, linenum, args[0]);
3923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926 err_code |= warnif_cond_requires_req(cond, file, linenum);
3927 }
3928 else if (*args[2]) {
3929 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3930 file, linenum, args[0], args[2]);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003935 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003936 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003937 wl->s = strdup(args[1]);
3938 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 else if (!strcmp(args[0], "errorloc") ||
3941 !strcmp(args[0], "errorloc302") ||
3942 !strcmp(args[0], "errorloc303")) { /* error location */
3943 int errnum, errlen;
3944 char *err;
3945
Willy Tarreau977b8e42006-12-29 14:19:17 +01003946 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003948
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003950 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
3954
3955 errnum = atol(args[1]);
3956 if (!strcmp(args[0], "errorloc303")) {
3957 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3958 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3959 } else {
3960 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3961 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3962 }
3963
Willy Tarreau0f772532006-12-23 20:51:41 +01003964 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3965 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003966 chunk_destroy(&curproxy->errmsg[rc]);
3967 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003968 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003971
3972 if (rc >= HTTP_ERR_SIZE) {
3973 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3974 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 free(err);
3976 }
3977 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003978 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3979 int errnum, errlen, fd;
3980 char *err;
3981 struct stat stat;
3982
3983 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003985
3986 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003987 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003990 }
3991
3992 fd = open(args[2], O_RDONLY);
3993 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3994 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3995 file, linenum, args[2], args[1]);
3996 if (fd >= 0)
3997 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004000 }
4001
Willy Tarreau27a674e2009-08-17 07:23:33 +02004002 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004003 errlen = stat.st_size;
4004 } else {
4005 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004006 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004008 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004009 }
4010
4011 err = malloc(errlen); /* malloc() must succeed during parsing */
4012 errnum = read(fd, err, errlen);
4013 if (errnum != errlen) {
4014 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4015 file, linenum, args[2], args[1]);
4016 close(fd);
4017 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004020 }
4021 close(fd);
4022
4023 errnum = atol(args[1]);
4024 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4025 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004026 chunk_destroy(&curproxy->errmsg[rc]);
4027 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004028 break;
4029 }
4030 }
4031
4032 if (rc >= HTTP_ERR_SIZE) {
4033 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4034 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004036 free(err);
4037 }
4038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004040 struct cfg_kw_list *kwl;
4041 int index;
4042
4043 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4044 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4045 if (kwl->kw[index].section != CFG_LISTEN)
4046 continue;
4047 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4048 /* prepare error message just in case */
4049 snprintf(trash, sizeof(trash),
4050 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004051 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4052 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004053 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004056 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004057 else if (rc > 0) {
4058 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004059 err_code |= ERR_WARN;
4060 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004061 }
Willy Tarreau93893792009-07-23 13:19:11 +02004062 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004063 }
4064 }
4065 }
4066
Willy Tarreau6daf3432008-01-22 16:44:08 +01004067 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 }
Willy Tarreau93893792009-07-23 13:19:11 +02004071 out:
4072 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073}
4074
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004075int
4076cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4077{
4078
4079 int err_code = 0;
4080 const char *err;
4081
4082 if (!strcmp(args[0], "userlist")) { /* new userlist */
4083 struct userlist *newul;
4084
4085 if (!*args[1]) {
4086 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4087 file, linenum, args[0]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
4091
4092 err = invalid_char(args[1]);
4093 if (err) {
4094 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4095 file, linenum, *err, args[0], args[1]);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099
4100 for (newul = userlist; newul; newul = newul->next)
4101 if (!strcmp(newul->name, args[1])) {
4102 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4103 file, linenum, args[1]);
4104 err_code |= ERR_WARN;
4105 goto out;
4106 }
4107
4108 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4109 if (!newul) {
4110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4111 err_code |= ERR_ALERT | ERR_ABORT;
4112 goto out;
4113 }
4114
4115 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4116 newul->name = strdup(args[1]);
4117
4118 if (!newul->groupusers | !newul->name) {
4119 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4120 err_code |= ERR_ALERT | ERR_ABORT;
4121 goto out;
4122 }
4123
4124 newul->next = userlist;
4125 userlist = newul;
4126
4127 } else if (!strcmp(args[0], "group")) { /* new group */
4128 int cur_arg, i;
4129 const char *err;
4130
4131 if (!*args[1]) {
4132 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4133 file, linenum, args[0]);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137
4138 err = invalid_char(args[1]);
4139 if (err) {
4140 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4141 file, linenum, *err, args[0], args[1]);
4142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
4144 }
4145
4146 for(i = 0; i < userlist->grpcnt; i++)
4147 if (!strcmp(userlist->groups[i], args[1])) {
4148 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4149 file, linenum, args[1], userlist->name);
4150 err_code |= ERR_ALERT;
4151 goto out;
4152 }
4153
4154 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4155 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4156 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
4160
4161 cur_arg = 2;
4162
4163 while (*args[cur_arg]) {
4164 if (!strcmp(args[cur_arg], "users")) {
4165 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 continue;
4168 } else {
4169 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4170 file, linenum, args[0]);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174 }
4175
4176 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4177 } else if (!strcmp(args[0], "user")) { /* new user */
4178 struct auth_users *newuser;
4179 int cur_arg;
4180
4181 if (!*args[1]) {
4182 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4183 file, linenum, args[0]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187
4188 for (newuser = userlist->users; newuser; newuser = newuser->next)
4189 if (!strcmp(newuser->user, args[1])) {
4190 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4191 file, linenum, args[1], userlist->name);
4192 err_code |= ERR_ALERT;
4193 goto out;
4194 }
4195
4196 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4197 if (!newuser) {
4198 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4199 err_code |= ERR_ALERT | ERR_ABORT;
4200 goto out;
4201 }
4202
4203 newuser->user = strdup(args[1]);
4204
4205 newuser->next = userlist->users;
4206 userlist->users = newuser;
4207
4208 cur_arg = 2;
4209
4210 while (*args[cur_arg]) {
4211 if (!strcmp(args[cur_arg], "password")) {
4212#ifndef CONFIG_HAP_CRYPT
4213 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4214 file, linenum);
4215 err_code |= ERR_ALERT;
4216#endif
4217 newuser->pass = strdup(args[cur_arg + 1]);
4218 cur_arg += 2;
4219 continue;
4220 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4221 newuser->pass = strdup(args[cur_arg + 1]);
4222 newuser->flags |= AU_O_INSECURE;
4223 cur_arg += 2;
4224 continue;
4225 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004226 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004227 cur_arg += 2;
4228 continue;
4229 } else {
4230 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4231 file, linenum, args[0]);
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235 }
4236 } else {
4237 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 }
4240
4241out:
4242 return err_code;
4243}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244
4245/*
4246 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004247 * Returns the error code, 0 if OK, or any combination of :
4248 * - ERR_ABORT: must abort ASAP
4249 * - ERR_FATAL: we can continue parsing but not start the service
4250 * - ERR_WARN: a warning has been emitted
4251 * - ERR_ALERT: an alert has been emitted
4252 * Only the two first ones can stop processing, the two others are just
4253 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004255int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004257 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 FILE *f;
4259 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004261 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004262
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 if ((f=fopen(file,"r")) == NULL)
4264 return -1;
4265
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004266 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004267 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004268 char *end;
4269 char *args[MAX_LINE_ARGS + 1];
4270 char *line = thisline;
4271
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 linenum++;
4273
4274 end = line + strlen(line);
4275
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004276 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4277 /* Check if we reached the limit and the last char is not \n.
4278 * Watch out for the last line without the terminating '\n'!
4279 */
4280 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004281 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004283 }
4284
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004286 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 line++;
4288
4289 arg = 0;
4290 args[arg] = line;
4291
4292 while (*line && arg < MAX_LINE_ARGS) {
4293 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4294 * C equivalent value. Other combinations left unchanged (eg: \1).
4295 */
4296 if (*line == '\\') {
4297 int skip = 0;
4298 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4299 *line = line[1];
4300 skip = 1;
4301 }
4302 else if (line[1] == 'r') {
4303 *line = '\r';
4304 skip = 1;
4305 }
4306 else if (line[1] == 'n') {
4307 *line = '\n';
4308 skip = 1;
4309 }
4310 else if (line[1] == 't') {
4311 *line = '\t';
4312 skip = 1;
4313 }
4314 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004315 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 unsigned char hex1, hex2;
4317 hex1 = toupper(line[2]) - '0';
4318 hex2 = toupper(line[3]) - '0';
4319 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4320 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4321 *line = (hex1<<4) + hex2;
4322 skip = 3;
4323 }
4324 else {
4325 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 }
4328 }
4329 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004330 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 end -= skip;
4332 }
4333 line++;
4334 }
4335 else if (*line == '#' || *line == '\n' || *line == '\r') {
4336 /* end of string, end of loop */
4337 *line = 0;
4338 break;
4339 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004340 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004342 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004343 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 line++;
4345 args[++arg] = line;
4346 }
4347 else {
4348 line++;
4349 }
4350 }
4351
4352 /* empty line */
4353 if (!**args)
4354 continue;
4355
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004356 if (*line) {
4357 /* we had to stop due to too many args.
4358 * Let's terminate the string, print the offending part then cut the
4359 * last arg.
4360 */
4361 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4362 line++;
4363 *line = '\0';
4364
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004365 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004366 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 args[arg] = line;
4369 }
4370
Willy Tarreau540abe42007-05-02 20:50:16 +02004371 /* zero out remaining args and ensure that at least one entry
4372 * is zeroed out.
4373 */
4374 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375 args[arg] = line;
4376 }
4377
Willy Tarreau3842f002009-06-14 11:39:52 +02004378 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004379 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004380 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004381 for (arg=0; *args[arg+1]; arg++)
4382 args[arg] = args[arg+1]; // shift args after inversion
4383 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004384 else if (!strcmp(args[0], "default")) {
4385 kwm = KWM_DEF;
4386 for (arg=0; *args[arg+1]; arg++)
4387 args[arg] = args[arg+1]; // shift args after inversion
4388 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004389
Willy Tarreau3842f002009-06-14 11:39:52 +02004390 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4391 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004392 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004393 }
4394
Willy Tarreau977b8e42006-12-29 14:19:17 +01004395 if (!strcmp(args[0], "listen") ||
4396 !strcmp(args[0], "frontend") ||
4397 !strcmp(args[0], "backend") ||
4398 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004399 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004401 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004402 cursection = strdup(args[0]);
4403 }
4404 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004406 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004407 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004408 } else if (!strcmp(args[0], "userlist")) {
4409 confsect = CFG_USERLIST;
4410 free(cursection);
4411 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 /* else it's a section keyword */
4414
4415 switch (confsect) {
4416 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 break;
4419 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004420 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004422 case CFG_USERLIST:
4423 err_code |= cfg_parse_users(file, linenum, args, kwm);
4424 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004426 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004429
4430 if (err_code & ERR_ABORT)
4431 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004433 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004434 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004436 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004437}
4438
Willy Tarreaubb925012009-07-23 13:36:36 +02004439/*
4440 * Returns the error code, 0 if OK, or any combination of :
4441 * - ERR_ABORT: must abort ASAP
4442 * - ERR_FATAL: we can continue parsing but not start the service
4443 * - ERR_WARN: a warning has been emitted
4444 * - ERR_ALERT: an alert has been emitted
4445 * Only the two first ones can stop processing, the two others are just
4446 * indicators.
4447 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004448int check_config_validity()
4449{
4450 int cfgerr = 0;
4451 struct proxy *curproxy = NULL;
4452 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004453 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004454 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004455 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004456
4457 /*
4458 * Now, check for the integrity of all that we have collected.
4459 */
4460
4461 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004462 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004464 /* first, we will invert the proxy list order */
4465 curproxy = NULL;
4466 while (proxy) {
4467 struct proxy *next;
4468
4469 next = proxy->next;
4470 proxy->next = curproxy;
4471 curproxy = proxy;
4472 if (!next)
4473 break;
4474 proxy = next;
4475 }
4476
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004478 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 }
4482
4483 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004484 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004485 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004486 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004487 unsigned int next_id;
4488
4489 if (!curproxy->uuid) {
4490 /* proxy ID not set, use automatic numbering with first
4491 * spare entry starting with next_pxid.
4492 */
4493 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4494 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4495 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004496 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004497 next_pxid++;
4498
Willy Tarreau55ea7572007-06-17 19:56:27 +02004499
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004501 /* ensure we don't keep listeners uselessly bound */
4502 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 curproxy = curproxy->next;
4504 continue;
4505 }
4506
Willy Tarreauff01a212009-03-15 13:46:16 +01004507 switch (curproxy->mode) {
4508 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004509 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004510 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004511 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4512 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004513 cfgerr++;
4514 }
4515
4516 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004517 Warning("config : servers will be ignored for %s '%s'.\n",
4518 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004519 break;
4520
4521 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004522 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004523 break;
4524
4525 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004526 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004527 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004528 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4529 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004530 cfgerr++;
4531 }
4532 break;
4533 }
4534
4535 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004536 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4537 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004538 cfgerr++;
4539 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004540
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004541 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004542 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004543 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004544 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4545 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004546 cfgerr++;
4547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004549 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004550 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4551 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004552 cfgerr++;
4553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004555 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004556 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4557 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004558 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004559 }
4560 }
4561 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4562 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4563 /* If no LB algo is set in a backend, and we're not in
4564 * transparent mode, dispatch mode nor proxy mode, we
4565 * want to use balance roundrobin by default.
4566 */
4567 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4568 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
4570 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004571
Willy Tarreau82936582007-11-30 15:20:09 +01004572 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4573 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004574 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4575 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004576 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004577 }
4578
Willy Tarreauef781042010-01-27 11:53:01 +01004579 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4580 curproxy->options &= ~PR_O2_CHK_SNDST;
4581 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4582 "send-state", proxy_type_str(curproxy), curproxy->id);
4583 err_code |= ERR_WARN;
4584 }
4585
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004586 /* if a default backend was specified, let's find it */
4587 if (curproxy->defbe.name) {
4588 struct proxy *target;
4589
Alex Williams96532db2009-11-01 21:27:13 -05004590 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004591 if (!target) {
4592 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4593 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004594 cfgerr++;
4595 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004596 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4597 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004598 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004599 } else {
4600 free(curproxy->defbe.name);
4601 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004602 /* we force the backend to be present on at least all of
4603 * the frontend's processes.
4604 */
4605 target->bind_proc = curproxy->bind_proc ?
4606 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 }
4608 }
4609
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004610 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004611 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4612 /* map jump target for ACT_SETBE in req_rep chain */
4613 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004614 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004615 struct proxy *target;
4616
Willy Tarreaua496b602006-12-17 23:15:24 +01004617 if (exp->action != ACT_SETBE)
4618 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004619
Alex Williams96532db2009-11-01 21:27:13 -05004620 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004621 if (!target) {
4622 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4623 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004624 cfgerr++;
4625 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004626 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4627 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004628 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004629 } else {
4630 free((void *)exp->replace);
4631 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004632 /* we force the backend to be present on at least all of
4633 * the frontend's processes.
4634 */
4635 target->bind_proc = curproxy->bind_proc ?
4636 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004637 }
4638 }
4639 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004640
4641 /* find the target proxy for 'use_backend' rules */
4642 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004643 struct proxy *target;
4644
Alex Williams96532db2009-11-01 21:27:13 -05004645 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004646
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004647 if (!target) {
4648 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4649 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004650 cfgerr++;
4651 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004652 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4653 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004654 cfgerr++;
4655 } else {
4656 free((void *)rule->be.name);
4657 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004658 /* we force the backend to be present on at least all of
4659 * the frontend's processes.
4660 */
4661 target->bind_proc = curproxy->bind_proc ?
4662 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004663 }
4664 }
4665
Emeric Brunb982a3d2010-01-04 15:45:53 +01004666 /* find the target table for 'stick' rules */
4667 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4668 struct proxy *target;
4669
Emeric Brun1d33b292010-01-04 15:47:17 +01004670 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4671 if (mrule->flags & STK_IS_STORE)
4672 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4673
Emeric Brunb982a3d2010-01-04 15:45:53 +01004674 if (mrule->table.name)
4675 target = findproxy(mrule->table.name, PR_CAP_BE);
4676 else
4677 target = curproxy;
4678
4679 if (!target) {
4680 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4681 curproxy->id, mrule->table.name);
4682 cfgerr++;
4683 }
4684 else if (target->table.size == 0) {
4685 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4686 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4687 cfgerr++;
4688 }
4689 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4690 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4691 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4692 cfgerr++;
4693 }
4694 else {
4695 free((void *)mrule->table.name);
4696 mrule->table.t = &(target->table);
4697 }
4698 }
4699
4700 /* find the target table for 'store response' rules */
4701 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4702 struct proxy *target;
4703
Emeric Brun1d33b292010-01-04 15:47:17 +01004704 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4705
Emeric Brunb982a3d2010-01-04 15:45:53 +01004706 if (mrule->table.name)
4707 target = findproxy(mrule->table.name, PR_CAP_BE);
4708 else
4709 target = curproxy;
4710
4711 if (!target) {
4712 Alert("Proxy '%s': unable to find store table '%s'.\n",
4713 curproxy->id, mrule->table.name);
4714 cfgerr++;
4715 }
4716 else if (target->table.size == 0) {
4717 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4718 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4719 cfgerr++;
4720 }
4721 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4722 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4723 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4724 cfgerr++;
4725 }
4726 else {
4727 free((void *)mrule->table.name);
4728 mrule->table.t = &(target->table);
4729 }
4730 }
4731
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004732 if (curproxy->uri_auth && !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
4733 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4734 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4735 "proxy", curproxy->id);
4736 cfgerr++;
4737 goto out_uri_auth_compat;
4738 }
4739
4740 if (curproxy->uri_auth && curproxy->uri_auth->userlist) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004741 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004742 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004743 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004744
Willy Tarreau95fa4692010-02-01 13:05:50 +01004745 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4746 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004747
4748 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004749 uri_auth_compat_req[i++] = "realm";
4750 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4751 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004752
Willy Tarreau95fa4692010-02-01 13:05:50 +01004753 uri_auth_compat_req[i++] = "unless";
4754 uri_auth_compat_req[i++] = "{";
4755 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4756 uri_auth_compat_req[i++] = "}";
4757 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004758
Willy Tarreau95fa4692010-02-01 13:05:50 +01004759 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4760 if (!req_acl) {
4761 cfgerr++;
4762 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004763 }
4764
Willy Tarreau95fa4692010-02-01 13:05:50 +01004765 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4766
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004767 if (curproxy->uri_auth->auth_realm) {
4768 free(curproxy->uri_auth->auth_realm);
4769 curproxy->uri_auth->auth_realm = NULL;
4770 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004771 }
4772out_uri_auth_compat:
4773
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004774 cfgerr += acl_find_targets(curproxy);
4775
Willy Tarreau2738a142006-07-08 17:28:09 +02004776 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004777 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004778 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004779 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004780 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004781 " | While not properly invalid, you will certainly encounter various problems\n"
4782 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004783 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004784 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004785 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004786 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004787
Willy Tarreau1fa31262007-12-03 00:36:16 +01004788 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4789 * We must still support older configurations, so let's find out whether those
4790 * parameters have been set or must be copied from contimeouts.
4791 */
4792 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004793 if (!curproxy->timeout.tarpit ||
4794 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004795 /* tarpit timeout not set. We search in the following order:
4796 * default.tarpit, curr.connect, default.connect.
4797 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004798 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004799 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004800 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004801 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004802 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004803 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004804 }
4805 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004806 (!curproxy->timeout.queue ||
4807 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004808 /* queue timeout not set. We search in the following order:
4809 * default.queue, curr.connect, default.connect.
4810 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004811 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004812 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004813 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004814 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004815 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004816 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004817 }
4818 }
4819
Willy Tarreauf3c69202006-07-09 16:42:34 +02004820 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004821 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4822 curproxy->check_req = (char *)malloc(curproxy->check_len);
4823 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004824 }
4825
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004826 /* The small pools required for the capture lists */
4827 if (curproxy->nb_req_cap)
4828 curproxy->req_cap_pool = create_pool("ptrcap",
4829 curproxy->nb_req_cap * sizeof(char *),
4830 MEM_F_SHARED);
4831 if (curproxy->nb_rsp_cap)
4832 curproxy->rsp_cap_pool = create_pool("ptrcap",
4833 curproxy->nb_rsp_cap * sizeof(char *),
4834 MEM_F_SHARED);
4835
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004836 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4837 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4838 MEM_F_SHARED);
4839
Willy Tarreau86034312006-12-29 00:10:33 +01004840 /* for backwards compatibility with "listen" instances, if
4841 * fullconn is not set but maxconn is set, then maxconn
4842 * is used.
4843 */
4844 if (!curproxy->fullconn)
4845 curproxy->fullconn = curproxy->maxconn;
4846
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 /* first, we will invert the servers list order */
4848 newsrv = NULL;
4849 while (curproxy->srv) {
4850 struct server *next;
4851
4852 next = curproxy->srv->next;
4853 curproxy->srv->next = newsrv;
4854 newsrv = curproxy->srv;
4855 if (!next)
4856 break;
4857 curproxy->srv = next;
4858 }
4859
Willy Tarreau20697042007-11-15 23:26:18 +01004860 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004861 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004863 /* We have to initialize the server lookup mechanism depending
4864 * on what LB algorithm was choosen.
4865 */
4866
4867 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4868 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4869 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004870 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4871 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4872 init_server_map(curproxy);
4873 } else {
4874 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4875 fwrr_init_server_groups(curproxy);
4876 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004877 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004878
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004879 case BE_LB_KIND_LC:
4880 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004881 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004882 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004883
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004884 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004885 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4886 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4887 chash_init_server_tree(curproxy);
4888 } else {
4889 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4890 init_server_map(curproxy);
4891 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004892 break;
4893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894
4895 if (curproxy->options & PR_O_LOGASAP)
4896 curproxy->to_log &= ~LW_BYTES;
4897
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004898 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4899 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4900 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4901 proxy_type_str(curproxy), curproxy->id);
4902 err_code |= ERR_WARN;
4903 }
4904
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004906 * ensure that we're not cross-dressing a TCP server into HTTP.
4907 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004908 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004909 newsrv = curproxy->srv;
4910 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004911 if (!newsrv->puid) {
4912 /* server ID not set, use automatic numbering with first
4913 * spare entry starting with next_svid.
4914 */
4915 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4916 newsrv->conf.id.key = newsrv->puid = next_id;
4917 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004918 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004919 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004920
Willy Tarreau21d2af32008-02-14 20:25:24 +01004921 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004922 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4923 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004924 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004925 }
4926 newsrv = newsrv->next;
4927 }
4928
4929 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 * If this server supports a maxconn parameter, it needs a dedicated
4931 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004932 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 */
4934 newsrv = curproxy->srv;
4935 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004936 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 /* Only 'minconn' was specified, or it was higher than or equal
4938 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4939 * this will avoid further useless expensive computations.
4940 */
4941 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004942 } else if (newsrv->maxconn && !newsrv->minconn) {
4943 /* minconn was not specified, so we set it to maxconn */
4944 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004945 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004946 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4947 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004948 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004951 if (newsrv->trackit) {
4952 struct proxy *px;
4953 struct server *srv;
4954 char *pname, *sname;
4955
4956 pname = newsrv->trackit;
4957 sname = strrchr(pname, '/');
4958
4959 if (sname)
4960 *sname++ = '\0';
4961 else {
4962 sname = pname;
4963 pname = NULL;
4964 }
4965
4966 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004967 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004968 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004969 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4970 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004971 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004972 cfgerr++;
4973 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004974 }
4975 } else
4976 px = curproxy;
4977
4978 srv = findserver(px, sname);
4979 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004980 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4981 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004982 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004983 cfgerr++;
4984 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004985 }
4986
4987 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004988 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004989 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004990 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004991 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004992 cfgerr++;
4993 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004994 }
4995
4996 if (curproxy != px &&
4997 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004998 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01004999 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005000 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005001 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005002 cfgerr++;
5003 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005004 }
5005
5006 newsrv->tracked = srv;
5007 newsrv->tracknext = srv->tracknext;
5008 srv->tracknext = newsrv;
5009
5010 free(newsrv->trackit);
5011 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005012 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 newsrv = newsrv->next;
5014 }
5015
Willy Tarreauc1a21672009-08-16 22:37:44 +02005016 if (curproxy->cap & PR_CAP_FE) {
5017 if (curproxy->tcp_req.inspect_delay ||
5018 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5019 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5020
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005021 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005022 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005023 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005024 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005025
5026 /* both TCP and HTTP must check switching rules */
5027 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5028 }
5029
5030 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005031 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005032 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005033 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005034 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005035
Emeric Brunb982a3d2010-01-04 15:45:53 +01005036 /* init table on backend capabilities proxy */
5037 stktable_init(&curproxy->table);
5038
Willy Tarreauc1a21672009-08-16 22:37:44 +02005039 /* If the backend does requires RDP cookie persistence, we have to
5040 * enable the corresponding analyser.
5041 */
5042 if (curproxy->options2 & PR_O2_RDPC_PRST)
5043 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5044 }
5045
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005046 listener = NULL;
5047 while (curproxy->listen) {
5048 struct listener *next;
5049
5050 next = curproxy->listen->next;
5051 curproxy->listen->next = listener;
5052 listener = curproxy->listen;
5053
5054 if (!next)
5055 break;
5056
5057 curproxy->listen = next;
5058 }
5059
Willy Tarreaue6b98942007-10-29 01:09:36 +01005060 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005061 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005062 listener = curproxy->listen;
5063 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005064 if (!listener->luid) {
5065 /* listener ID not set, use automatic numbering with first
5066 * spare entry starting with next_luid.
5067 */
5068 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5069 listener->conf.id.key = listener->luid = next_id;
5070 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005071 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005072 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005073
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005074 /* enable separate counters */
5075 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5076 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5077 if (!listener->name) {
5078 sprintf(trash, "sock-%d", listener->luid);
5079 listener->name = strdup(trash);
5080 }
5081 }
5082
Willy Tarreaue6b98942007-10-29 01:09:36 +01005083 if (curproxy->options & PR_O_TCP_NOLING)
5084 listener->options |= LI_O_NOLINGER;
5085 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005086 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005087 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005088 listener->accept = event_accept;
5089 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005090 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005091 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005092
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005093 /* smart accept mode is automatic in HTTP mode */
5094 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5095 (curproxy->mode == PR_MODE_HTTP &&
5096 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5097 listener->options |= LI_O_NOQUICKACK;
5098
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005099 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005100 listener = listener->next;
5101 }
5102
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 curproxy = curproxy->next;
5104 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005105
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005106 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5107 struct auth_users *curuser;
5108 int g;
5109
5110 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5111 unsigned int group_mask = 0;
5112 char *group = NULL;
5113
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005114 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005115 continue;
5116
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005117 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005118
5119 for (g = 0; g < curuserlist->grpcnt; g++)
5120 if (!strcmp(curuserlist->groups[g], group))
5121 break;
5122
5123 if (g == curuserlist->grpcnt) {
5124 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5125 curuserlist->name, group, curuser->user);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
5129
5130 group_mask |= (1 << g);
5131 }
5132
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005133 free(curuser->u.groups);
5134 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005135 }
5136
5137 for (g = 0; g < curuserlist->grpcnt; g++) {
5138 char *user = NULL;
5139
5140 if (!curuserlist->groupusers[g])
5141 continue;
5142
5143 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5144 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5145 if (!strcmp(curuser->user, user))
5146 break;
5147
5148 if (!curuser) {
5149 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5150 curuserlist->name, user, curuserlist->groups[g]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005155 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005156 }
5157
5158 free(curuserlist->groupusers[g]);
5159 }
5160
5161 free(curuserlist->groupusers);
5162
5163#ifdef DEBUG_AUTH
5164 for (g = 0; g < curuserlist->grpcnt; g++) {
5165 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5166
5167 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5168 if (curuser->group_mask & (1 << g))
5169 fprintf(stderr, " %s", curuser->user);
5170 }
5171
5172 fprintf(stderr, "\n");
5173 }
5174#endif
5175
5176 }
5177
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005178 /*
5179 * Recount currently required checks.
5180 */
5181
5182 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5183 int optnum;
5184
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005185 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5186 if (curproxy->options & cfg_opts[optnum].val)
5187 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005188
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005189 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5190 if (curproxy->options2 & cfg_opts2[optnum].val)
5191 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005192 }
5193
Willy Tarreaubb925012009-07-23 13:36:36 +02005194 if (cfgerr > 0)
5195 err_code |= ERR_ALERT | ERR_FATAL;
5196 out:
5197 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198}
5199
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005200/*
5201 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5202 * parsing sessions.
5203 */
5204void cfg_register_keywords(struct cfg_kw_list *kwl)
5205{
5206 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5207}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005209/*
5210 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5211 */
5212void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5213{
5214 LIST_DEL(&kwl->list);
5215 LIST_INIT(&kwl->list);
5216}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217
5218/*
5219 * Local variables:
5220 * c-indent-level: 8
5221 * c-basic-offset: 8
5222 * End:
5223 */