blob: 680b546834e4e0dd16dafb5353a0bc2f721326aa [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010042#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010045#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020046#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020047#include <proto/lb_fwlc.h>
48#include <proto/lb_fwrr.h>
49#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010051#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020052#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010053#include <proto/protocols.h>
54#include <proto/proto_tcp.h>
55#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010056#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010058#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010060#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061
62
Willy Tarreauf3c69202006-07-09 16:42:34 +020063/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
64 * ssl-hello-chk option to ensure that the remote server speaks SSL.
65 *
66 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
67 */
68const char sslv3_client_hello_pkt[] = {
69 "\x16" /* ContentType : 0x16 = Hanshake */
70 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
71 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
72 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
73 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
74 "\x03\x00" /* Hello Version : 0x0300 = v3 */
75 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
76 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
77 "\x00" /* Session ID length : empty (no session ID) */
78 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
79 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
80 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
81 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
82 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
83 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
84 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
85 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
86 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
87 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
88 "\x00\x38" "\x00\x39" "\x00\x3A"
89 "\x01" /* Compression Length : 0x01 = 1 byte for types */
90 "\x00" /* Compression Type : 0x00 = NULL compression */
91};
92
Willy Tarreau3842f002009-06-14 11:39:52 +020093/* various keyword modifiers */
94enum kw_mod {
95 KWM_STD = 0, /* normal */
96 KWM_NO, /* "no" prefixed before the keyword */
97 KWM_DEF, /* "default" prefixed before the keyword */
98};
99
Willy Tarreau13943ab2006-12-31 00:24:10 +0100100/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100101struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102 const char *name;
103 unsigned int val;
104 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106};
107
108/* proxy->options */
109static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100112 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100114 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
116 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100117 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100118 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
120 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100121 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
123 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100124 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
126 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100127#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100128 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100129#endif
130
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100132};
133
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100134/* proxy->options2 */
135static const struct cfg_opt cfg_opts2[] =
136{
137#ifdef CONFIG_HAP_LINUX_SPLICE
138 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
140 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
141#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200142 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
143 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200144 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
145 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200146 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200147 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200148 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200149 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200150 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100151 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152 { NULL, 0, 0, 0 }
153};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154
Willy Tarreau6daf3432008-01-22 16:44:08 +0100155static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
157int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100158int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200160/* List head of all known configuration keywords */
161static struct cfg_kw_list cfg_keywords = {
162 .list = LIST_HEAD_INIT(cfg_keywords.list)
163};
164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/*
166 * converts <str> to a list of listeners which are dynamically allocated.
167 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
168 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
169 * - <port> is a numerical port from 1 to 65535 ;
170 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
171 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200174static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175{
176 struct listener *l;
177 char *c, *next, *range, *dupstr;
178 int port, end;
179
180 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182 while (next && *next) {
183 struct sockaddr_storage ss;
184
185 str = next;
186 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100187 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 *next++ = 0;
189 }
190
191 /* 2) look for the addr/port delimiter, it's the last colon. */
192 if ((range = strrchr(str, ':')) == NULL) {
193 Alert("Missing port number: '%s'\n", str);
194 goto fail;
195 }
196
197 *range++ = 0;
198
199 if (strrchr(str, ':') != NULL) {
200 /* IPv6 address contains ':' */
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET6;
203
204 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
205 Alert("Invalid server address: '%s'\n", str);
206 goto fail;
207 }
208 }
209 else {
210 memset(&ss, 0, sizeof(ss));
211 ss.ss_family = AF_INET;
212
213 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
214 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
215 }
216 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
217 struct hostent *he;
218
219 if ((he = gethostbyname(str)) == NULL) {
220 Alert("Invalid server name: '%s'\n", str);
221 goto fail;
222 }
223 else
224 ((struct sockaddr_in *)&ss)->sin_addr =
225 *(struct in_addr *) *(he->h_addr_list);
226 }
227 }
228
229 /* 3) look for the port-end delimiter */
230 if ((c = strchr(range, '-')) != NULL) {
231 *c++ = 0;
232 end = atol(c);
233 }
234 else {
235 end = atol(range);
236 }
237
238 port = atol(range);
239
240 if (port < 1 || port > 65535) {
241 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
242 goto fail;
243 }
244
245 if (end < 1 || end > 65535) {
246 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
247 goto fail;
248 }
249
250 for (; port <= end; port++) {
251 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200252 l->next = curproxy->listen;
253 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 l->state = LI_INIT;
258
259 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100261 tcpv6_add_listener(l);
262 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 tcpv4_add_listener(l);
265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200266
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 } /* end for(port) */
269 } /* end while(next) */
270 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 fail:
273 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200274 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275}
276
Willy Tarreau977b8e42006-12-29 14:19:17 +0100277/*
278 * Sends a warning if proxy <proxy> does not have at least one of the
279 * capabilities in <cap>. An optionnal <hint> may be added at the end
280 * of the warning to help the user. Returns 1 if a warning was emitted
281 * or 0 if the condition is valid.
282 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100283int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100284{
285 char *msg;
286
287 switch (cap) {
288 case PR_CAP_BE: msg = "no backend"; break;
289 case PR_CAP_FE: msg = "no frontend"; break;
290 case PR_CAP_RS: msg = "no ruleset"; break;
291 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
292 default: msg = "not enough"; break;
293 }
294
295 if (!(proxy->cap & cap)) {
296 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100297 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298 return 1;
299 }
300 return 0;
301}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302
Willy Tarreau61d18892009-03-31 10:49:21 +0200303/* Report a warning if a rule is placed after a 'block' rule.
304 * Return 1 if the warning has been emitted, otherwise 0.
305 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100306int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200307{
308 if (!LIST_ISEMPTY(&proxy->block_cond)) {
309 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
310 file, line, arg);
311 return 1;
312 }
313 return 0;
314}
315
316/* Report a warning if a rule is placed after a reqrewrite rule.
317 * Return 1 if the warning has been emitted, otherwise 0.
318 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100319int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200320{
321 if (proxy->req_exp) {
322 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
323 file, line, arg);
324 return 1;
325 }
326 return 0;
327}
328
329/* Report a warning if a rule is placed after a reqadd rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100334 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a redirect rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a 'use_backend' rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
360 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
372 warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
381 warnif_rule_after_redirect(proxy, file, line, arg) ||
382 warnif_rule_after_use_backend(proxy, file, line, arg);
383}
384
385/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100392/* Report it if a request ACL condition uses some response-only parameters. It
393 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
394 * Note that <cond> may be NULL and then will be ignored.
395 */
396static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
397{
398 struct acl *acl;
399
400 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
401 return 0;
402
403 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
404 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
405 file, line, acl ? acl->name : "(unknown)");
406 return ERR_WARN;
407}
408
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100409/* Report it if a request ACL condition uses some request-only volatile parameters.
410 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
421 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 * parse a line in a <global> section. Returns the error code, 0 if OK, or
429 * any combination of :
430 * - ERR_ABORT: must abort ASAP
431 * - ERR_FATAL: we can continue parsing but not start the service
432 * - ERR_WARN: a warning has been emitted
433 * - ERR_ALERT: an alert has been emitted
434 * Only the two first ones can stop processing, the two others are just
435 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200436 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200437int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438{
Willy Tarreau058e9072009-07-20 09:30:05 +0200439 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440
441 if (!strcmp(args[0], "global")) { /* new section */
442 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444 }
445 else if (!strcmp(args[0], "daemon")) {
446 global.mode |= MODE_DAEMON;
447 }
448 else if (!strcmp(args[0], "debug")) {
449 global.mode |= MODE_DEBUG;
450 }
451 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100452 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200454 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100455 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200456 }
457 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100458 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100461 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100463 else if (!strcmp(args[0], "nosplice")) {
464 global.tune.options &= ~GTUNE_USE_SPLICE;
465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 else if (!strcmp(args[0], "quiet")) {
467 global.mode |= MODE_QUIET;
468 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200469 else if (!strcmp(args[0], "tune.maxpollevents")) {
470 if (global.tune.maxpollevents != 0) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT;
473 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200479 }
480 global.tune.maxpollevents = atol(args[1]);
481 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100482 else if (!strcmp(args[0], "tune.maxaccept")) {
483 if (global.tune.maxaccept != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200485 err_code |= ERR_ALERT;
486 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100487 }
488 if (*(args[1]) == 0) {
489 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200490 err_code |= ERR_ALERT | ERR_FATAL;
491 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100492 }
493 global.tune.maxaccept = atol(args[1]);
494 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200495 else if (!strcmp(args[0], "tune.bufsize")) {
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.tune.bufsize = atol(args[1]);
502 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
503 global.tune.maxrewrite = global.tune.bufsize / 2;
504 }
505 else if (!strcmp(args[0], "tune.maxrewrite")) {
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.tune.maxrewrite = atol(args[1]);
512 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
513 global.tune.maxrewrite = global.tune.bufsize / 2;
514 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100515 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
516 if (global.tune.client_rcvbuf != 0) {
517 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT;
519 goto out;
520 }
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.client_rcvbuf = atol(args[1]);
527 }
528 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
529 if (global.tune.server_rcvbuf != 0) {
530 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT;
532 goto out;
533 }
534 if (*(args[1]) == 0) {
535 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
536 err_code |= ERR_ALERT | ERR_FATAL;
537 goto out;
538 }
539 global.tune.server_rcvbuf = atol(args[1]);
540 }
541 else if (!strcmp(args[0], "tune.sndbuf.client")) {
542 if (global.tune.client_sndbuf != 0) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT;
545 goto out;
546 }
547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.client_sndbuf = atol(args[1]);
553 }
554 else if (!strcmp(args[0], "tune.sndbuf.server")) {
555 if (global.tune.server_sndbuf != 0) {
556 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
557 err_code |= ERR_ALERT;
558 goto out;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT | ERR_FATAL;
563 goto out;
564 }
565 global.tune.server_sndbuf = atol(args[1]);
566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 else if (!strcmp(args[0], "uid")) {
568 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200569 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 global.uid = atol(args[1]);
579 }
580 else if (!strcmp(args[0], "gid")) {
581 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200582 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.gid = atol(args[1]);
592 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200593 /* user/group name handling */
594 else if (!strcmp(args[0], "user")) {
595 struct passwd *ha_user;
596 if (global.uid != 0) {
597 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT;
599 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 }
601 errno = 0;
602 ha_user = getpwnam(args[1]);
603 if (ha_user != NULL) {
604 global.uid = (int)ha_user->pw_uid;
605 }
606 else {
607 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 }
610 }
611 else if (!strcmp(args[0], "group")) {
612 struct group *ha_group;
613 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200614 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 }
618 errno = 0;
619 ha_group = getgrnam(args[1]);
620 if (ha_group != NULL) {
621 global.gid = (int)ha_group->gr_gid;
622 }
623 else {
624 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200626 }
627 }
628 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "nbproc")) {
630 if (global.nbproc != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.nbproc = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "maxconn")) {
643 if (global.maxconn != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.maxconn = atol(args[1]);
654#ifdef SYSTEM_MAXCONN
655 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
656 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
657 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200659 }
660#endif /* SYSTEM_MAXCONN */
661 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100662 else if (!strcmp(args[0], "maxpipes")) {
663 if (global.maxpipes != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100672 }
673 global.maxpipes = atol(args[1]);
674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "ulimit-n")) {
676 if (global.rlimit_nofile != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.rlimit_nofile = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "chroot")) {
689 if (global.chroot != NULL) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.chroot = strdup(args[1]);
700 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200701 else if (!strcmp(args[0], "description")) {
702 int i, len=0;
703 char *d;
704
705 if (!*args[1]) {
706 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711
712 for(i=1; *args[i]; i++)
713 len += strlen(args[i])+1;
714
715 if (global.desc)
716 free(global.desc);
717
718 global.desc = d = (char *)calloc(1, len);
719
720 d += sprintf(d, "%s", args[1]);
721 for(i=2; *args[i]; i++)
722 d += sprintf(d, " %s", args[i]);
723 }
724 else if (!strcmp(args[0], "node")) {
725 int i;
726 char c;
727
728 for (i=0; args[1][i]; i++) {
729 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100730 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
731 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200732 break;
733 }
734
735 if (!i || args[1][i]) {
736 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
737 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
738 file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741 }
742
743 if (global.node)
744 free(global.node);
745
746 global.node = strdup(args[1]);
747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 else if (!strcmp(args[0], "pidfile")) {
749 if (global.pidfile != NULL) {
750 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT;
752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 }
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 global.pidfile = strdup(args[1]);
760 }
761 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100762 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200763 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764
765 if (*(args[1]) == 0 || *(args[2]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770
771 facility = get_log_facility(args[2]);
772 if (facility < 0) {
773 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777
778 level = 7; /* max syslog level = debug */
779 if (*(args[3])) {
780 level = get_log_level(args[3]);
781 if (level < 0) {
782 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT | ERR_FATAL;
784 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
786 }
787
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200788 minlvl = 0; /* limit syslog level to this level (emerg) */
789 if (*(args[4])) {
790 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200792 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
794 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200795 }
796 }
797
Robert Tsai81ae1952007-12-05 10:47:29 +0100798 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100799 struct sockaddr_un *sk = str2sun(args[1]);
800 if (!sk) {
801 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
802 args[1], (int)sizeof(sk->sun_path) - 1);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100807 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100808 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100809 struct sockaddr_in *sk = str2sa(args[1]);
810 if (!sk) {
811 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100816 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100817 if (!logsrv.u.in.sin_port)
818 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820
821 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100822 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 global.logfac1 = facility;
824 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200825 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100828 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 global.logfac2 = facility;
830 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200831 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 else {
834 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200837 }
838 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
839 if (global.spread_checks != 0) {
840 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200841 err_code |= ERR_ALERT;
842 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200843 }
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200848 }
849 global.spread_checks = atol(args[1]);
850 if (global.spread_checks < 0 || global.spread_checks > 50) {
851 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200852 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 }
855 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200856 struct cfg_kw_list *kwl;
857 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200858 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200859
860 list_for_each_entry(kwl, &cfg_keywords.list, list) {
861 for (index = 0; kwl->kw[index].kw != NULL; index++) {
862 if (kwl->kw[index].section != CFG_GLOBAL)
863 continue;
864 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
865 /* prepare error message just in case */
866 snprintf(trash, sizeof(trash),
867 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200868 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
869 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200870 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200871 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200872 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200873 else if (rc > 0) {
874 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200875 err_code |= ERR_WARN;
876 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200877 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200878 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200879 }
880 }
881 }
882
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200886
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 out:
888 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
Willy Tarreau97cb7802010-01-03 20:23:58 +0100891/* Perform the most basic initialization of a proxy :
892 * memset(), list_init(*), reset_timeouts(*).
893 */
894static void init_new_proxy(struct proxy *p)
895{
896 memset(p, 0, sizeof(struct proxy));
897 LIST_INIT(&p->pendconns);
898 LIST_INIT(&p->acl);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +0100899 LIST_INIT(&p->req_acl);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100900 LIST_INIT(&p->block_cond);
901 LIST_INIT(&p->redirect_rules);
902 LIST_INIT(&p->mon_fail_cond);
903 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100904 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100905 LIST_INIT(&p->sticking_rules);
906 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100907 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100908 LIST_INIT(&p->req_add);
909 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100910
911 /* Timeouts are defined as -1 */
912 proxy_reset_timeouts(p);
913}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200915void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100917 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 defproxy.mode = PR_MODE_TCP;
919 defproxy.state = PR_STNEW;
920 defproxy.maxconn = cfg_maxpconn;
921 defproxy.conn_retries = CONN_RETRIES;
922 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100923
924 defproxy.defsrv.inter = DEF_CHKINTR;
925 defproxy.defsrv.fastinter = 0;
926 defproxy.defsrv.downinter = 0;
927 defproxy.defsrv.rise = DEF_RISETIME;
928 defproxy.defsrv.fall = DEF_FALLTIME;
929 defproxy.defsrv.check_port = 0;
930 defproxy.defsrv.maxqueue = 0;
931 defproxy.defsrv.minconn = 0;
932 defproxy.defsrv.maxconn = 0;
933 defproxy.defsrv.slowstart = 0;
934 defproxy.defsrv.onerror = DEF_HANA_ONERR;
935 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
936 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937}
938
Willy Tarreauade5ec42010-01-28 19:33:49 +0100939
940static int create_cond_regex_rule(const char *file, int line,
941 struct proxy *px, int dir, int action, int flags,
942 const char *cmd, const char *reg, const char *repl,
943 const char **cond_start)
944{
945 regex_t *preg = NULL;
946 const char *err;
947 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100948 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100949
950 if (px == &defproxy) {
951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto err;
954 }
955
956 if (*reg == 0) {
957 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto err;
960 }
961
962 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
963 err_code |= ERR_WARN;
964
Willy Tarreau5321c422010-01-28 20:35:13 +0100965 if (cond_start &&
966 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
967 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
968 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
969 file, line, cmd);
970 err_code |= ERR_ALERT | ERR_FATAL;
971 goto err;
972 }
973 }
974 else if (cond_start && **cond_start) {
975 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
976 file, line, cmd, *cond_start);
977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto err;
979 }
980
981 if (dir == ACL_DIR_REQ)
982 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100983 else
984 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100985
Willy Tarreauade5ec42010-01-28 19:33:49 +0100986 preg = calloc(1, sizeof(regex_t));
987 if (!preg) {
988 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
989 err_code = ERR_ALERT | ERR_FATAL;
990 goto err;
991 }
992
993 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
994 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
995 err_code = ERR_ALERT | ERR_FATAL;
996 goto err;
997 }
998
999 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001000 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001001 if (repl && err) {
1002 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1003 file, line, cmd, *err);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto err;
1006 }
1007
1008 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1009 err_code |= ERR_WARN;
1010
1011 return err_code;
1012 err:
1013 free(preg);
1014 return err_code;
1015}
1016
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001018 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001019 * Returns the error code, 0 if OK, or any combination of :
1020 * - ERR_ABORT: must abort ASAP
1021 * - ERR_FATAL: we can continue parsing but not start the service
1022 * - ERR_WARN: a warning has been emitted
1023 * - ERR_ALERT: an alert has been emitted
1024 * Only the two first ones can stop processing, the two others are just
1025 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001027int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028{
1029 static struct proxy *curproxy = NULL;
1030 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001031 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001032 int rc;
1033 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001034 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001035 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036
Willy Tarreau977b8e42006-12-29 14:19:17 +01001037 if (!strcmp(args[0], "listen"))
1038 rc = PR_CAP_LISTEN;
1039 else if (!strcmp(args[0], "frontend"))
1040 rc = PR_CAP_FE | PR_CAP_RS;
1041 else if (!strcmp(args[0], "backend"))
1042 rc = PR_CAP_BE | PR_CAP_RS;
1043 else if (!strcmp(args[0], "ruleset"))
1044 rc = PR_CAP_RS;
1045 else
1046 rc = PR_CAP_NONE;
1047
1048 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (!*args[1]) {
1050 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1051 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001053 err_code |= ERR_ALERT | ERR_ABORT;
1054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001056
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001057 err = invalid_char(args[1]);
1058 if (err) {
1059 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1060 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001062 }
1063
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001064 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1065 /*
1066 * If there are two proxies with the same name only following
1067 * combinations are allowed:
1068 *
1069 * listen backend frontend ruleset
1070 * listen - - - -
1071 * backend - - OK -
1072 * frontend - OK - -
1073 * ruleset - - - -
1074 */
1075
1076 if (!strcmp(curproxy->id, args[1]) &&
1077 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1078 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001079 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1080 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1081 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001082 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001083 }
1084 }
1085
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1087 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001088 err_code |= ERR_ALERT | ERR_ABORT;
1089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001091
Willy Tarreau97cb7802010-01-03 20:23:58 +01001092 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 curproxy->next = proxy;
1094 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001095 curproxy->conf.file = file;
1096 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001097 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001099 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100
1101 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001102 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001103 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001104 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001105 err_code |= ERR_FATAL;
1106 goto out;
1107 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001108 new = curproxy->listen;
1109 while (new != last) {
1110 new->conf.file = file;
1111 new->conf.line = linenum;
1112 new = new->next;
1113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 global.maxsock++;
1115 }
1116
1117 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001118 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001122 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001123 curproxy->no_options = defproxy.no_options;
1124 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001125 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001126 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001127 curproxy->except_net = defproxy.except_net;
1128 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001129 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001130 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001132 if (defproxy.fwdfor_hdr_len) {
1133 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1134 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1135 }
1136
Willy Tarreaub86db342009-11-30 11:50:16 +01001137 if (defproxy.orgto_hdr_len) {
1138 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1139 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1140 }
1141
Willy Tarreau977b8e42006-12-29 14:19:17 +01001142 if (curproxy->cap & PR_CAP_FE) {
1143 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001144 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001145 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146
1147 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001148 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1149 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150
1151 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153
Willy Tarreau977b8e42006-12-29 14:19:17 +01001154 if (curproxy->cap & PR_CAP_BE) {
1155 curproxy->fullconn = defproxy.fullconn;
1156 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157
Willy Tarreau977b8e42006-12-29 14:19:17 +01001158 if (defproxy.check_req)
1159 curproxy->check_req = strdup(defproxy.check_req);
1160 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161
Willy Tarreau977b8e42006-12-29 14:19:17 +01001162 if (defproxy.cookie_name)
1163 curproxy->cookie_name = strdup(defproxy.cookie_name);
1164 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001165 if (defproxy.cookie_domain)
1166 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001167
Emeric Brun647caf12009-06-30 17:57:00 +02001168 if (defproxy.rdp_cookie_name)
1169 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1170 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1171
Willy Tarreau01732802007-11-01 22:48:15 +01001172 if (defproxy.url_param_name)
1173 curproxy->url_param_name = strdup(defproxy.url_param_name);
1174 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001175
Benoitaffb4812009-03-25 13:02:10 +01001176 if (defproxy.hh_name)
1177 curproxy->hh_name = strdup(defproxy.hh_name);
1178 curproxy->hh_len = defproxy.hh_len;
1179 curproxy->hh_match_domain = defproxy.hh_match_domain;
1180
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001181 if (defproxy.iface_name)
1182 curproxy->iface_name = strdup(defproxy.iface_name);
1183 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001186 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 if (defproxy.capture_name)
1188 curproxy->capture_name = strdup(defproxy.capture_name);
1189 curproxy->capture_namelen = defproxy.capture_namelen;
1190 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192
Willy Tarreau977b8e42006-12-29 14:19:17 +01001193 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001194 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001195 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001196 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001197 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 curproxy->uri_auth = defproxy.uri_auth;
1199 curproxy->mon_net = defproxy.mon_net;
1200 curproxy->mon_mask = defproxy.mon_mask;
1201 if (defproxy.monitor_uri)
1202 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1203 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001204 if (defproxy.defbe.name)
1205 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001206 }
1207
1208 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001209 curproxy->timeout.connect = defproxy.timeout.connect;
1210 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001211 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001212 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001213 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001214 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001215 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001216 curproxy->source_addr = defproxy.source_addr;
1217 }
1218
Willy Tarreaubaaee002006-06-26 02:48:02 +02001219 curproxy->mode = defproxy.mode;
1220 curproxy->logfac1 = defproxy.logfac1;
1221 curproxy->logsrv1 = defproxy.logsrv1;
1222 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001223 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224 curproxy->logfac2 = defproxy.logfac2;
1225 curproxy->logsrv2 = defproxy.logsrv2;
1226 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001229 curproxy->conf.used_listener_id = EB_ROOT;
1230 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001231
Willy Tarreau93893792009-07-23 13:19:11 +02001232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1235 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001236 /* FIXME-20070101: we should do this too at the end of the
1237 * config parsing to free all default values.
1238 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001239 free(defproxy.check_req);
1240 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001241 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001242 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001243 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001244 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001245 free(defproxy.capture_name);
1246 free(defproxy.monitor_uri);
1247 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001248 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001249 free(defproxy.fwdfor_hdr_name);
1250 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001251 free(defproxy.orgto_hdr_name);
1252 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001253
Willy Tarreaua534fea2008-08-03 12:19:50 +02001254 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001255 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001256
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 /* we cannot free uri_auth because it might already be used */
1258 init_default_instance();
1259 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001260 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001262 }
1263 else if (curproxy == NULL) {
1264 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 }
1268
Willy Tarreau977b8e42006-12-29 14:19:17 +01001269
1270 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001271 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001272 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001273 int cur_arg;
1274
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275 if (curproxy == &defproxy) {
1276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001280 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001281 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001282
1283 if (strchr(args[1], ':') == NULL) {
1284 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001288 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001289
1290 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001291 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001295
Willy Tarreau90a570f2009-10-04 20:54:54 +02001296 new_listen = curproxy->listen;
1297 while (new_listen != last_listen) {
1298 new_listen->conf.file = file;
1299 new_listen->conf.line = linenum;
1300 new_listen = new_listen->next;
1301 }
1302
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001303 cur_arg = 2;
1304 while (*(args[cur_arg])) {
1305 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1306#ifdef SO_BINDTODEVICE
1307 struct listener *l;
1308
1309 if (!*args[cur_arg + 1]) {
1310 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001314 }
1315
1316 for (l = curproxy->listen; l != last_listen; l = l->next)
1317 l->interface = strdup(args[cur_arg + 1]);
1318
1319 global.last_checks |= LSTCHK_NETADM;
1320
1321 cur_arg += 2;
1322 continue;
1323#else
1324 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1325 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001328#endif
1329 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001330 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1331#ifdef TCP_MAXSEG
1332 struct listener *l;
1333 int mss;
1334
1335 if (!*args[cur_arg + 1]) {
1336 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001340 }
1341
1342 mss = str2uic(args[cur_arg + 1]);
1343 if (mss < 1 || mss > 65535) {
1344 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001348 }
1349
1350 for (l = curproxy->listen; l != last_listen; l = l->next)
1351 l->maxseg = mss;
1352
1353 cur_arg += 2;
1354 continue;
1355#else
1356 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1357 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001358 err_code |= ERR_ALERT | ERR_FATAL;
1359 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001360#endif
1361 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001362
1363 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1364#ifdef TCP_DEFER_ACCEPT
1365 struct listener *l;
1366
1367 for (l = curproxy->listen; l != last_listen; l = l->next)
1368 l->options |= LI_O_DEF_ACCEPT;
1369
1370 cur_arg ++;
1371 continue;
1372#else
1373 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1374 file, linenum, args[0], args[cur_arg]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377#endif
1378 }
1379
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001380 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001381#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001382 struct listener *l;
1383
1384 for (l = curproxy->listen; l != last_listen; l = l->next)
1385 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001386
1387 cur_arg ++;
1388 continue;
1389#else
1390 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1391 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001394#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001395 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001396
1397 if (!strcmp(args[cur_arg], "name")) {
1398 struct listener *l;
1399
1400 for (l = curproxy->listen; l != last_listen; l = l->next)
1401 l->name = strdup(args[cur_arg + 1]);
1402
1403 cur_arg += 2;
1404 continue;
1405 }
1406
1407 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001408 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001409 struct listener *l;
1410
1411 if (curproxy->listen->next != last_listen) {
1412 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1413 file, linenum, args[cur_arg]);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto out;
1416 }
1417
1418 if (!*args[cur_arg + 1]) {
1419 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1420 file, linenum, args[cur_arg]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424
1425 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001426 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001427
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001428 if (curproxy->listen->luid <= 0) {
1429 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001430 file, linenum);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433 }
1434
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001435 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1436 if (node) {
1437 l = container_of(node, struct listener, conf.id);
1438 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1439 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
1442 }
1443 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1444
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001445 cur_arg += 2;
1446 continue;
1447 }
1448
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001449 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_ALERT | ERR_FATAL;
1452 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 }
1457 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1458 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1459 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 /* flush useless bits */
1468 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001471 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474
Willy Tarreau1c47f852006-07-09 08:22:27 +02001475 if (!*args[1]) {
1476 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1477 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001480 }
1481
Willy Tarreaua534fea2008-08-03 12:19:50 +02001482 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001483 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001484 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001485 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001486 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1487
Willy Tarreau93893792009-07-23 13:19:11 +02001488 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1491 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1492 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1493 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1494 else {
1495 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 }
1499 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001500 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001501 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001502
1503 if (curproxy == &defproxy) {
1504 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001508 }
1509
1510 if (!*args[1]) {
1511 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_ALERT | ERR_FATAL;
1514 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001515 }
1516
1517 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001518 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001519
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001520 if (curproxy->uuid <= 0) {
1521 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001525 }
1526
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001527 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1528 if (node) {
1529 struct proxy *target = container_of(node, struct proxy, conf.id);
1530 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1531 file, linenum, proxy_type_str(curproxy), curproxy->id,
1532 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1533 err_code |= ERR_ALERT | ERR_FATAL;
1534 goto out;
1535 }
1536 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001537 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001538 else if (!strcmp(args[0], "description")) {
1539 int i, len=0;
1540 char *d;
1541
Cyril Bonté99ed3272010-01-24 23:29:44 +01001542 if (curproxy == &defproxy) {
1543 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1544 file, linenum, args[0]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001549 if (!*args[1]) {
1550 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1551 file, linenum, args[0]);
1552 return -1;
1553 }
1554
1555 for(i=1; *args[i]; i++)
1556 len += strlen(args[i])+1;
1557
1558 d = (char *)calloc(1, len);
1559 curproxy->desc = d;
1560
1561 d += sprintf(d, "%s", args[1]);
1562 for(i=2; *args[i]; i++)
1563 d += sprintf(d, " %s", args[i]);
1564
1565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1567 curproxy->state = PR_STSTOPPED;
1568 }
1569 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1570 curproxy->state = PR_STNEW;
1571 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001572 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1573 int cur_arg = 1;
1574 unsigned int set = 0;
1575
1576 while (*args[cur_arg]) {
1577 int u;
1578 if (strcmp(args[cur_arg], "all") == 0) {
1579 set = 0;
1580 break;
1581 }
1582 else if (strcmp(args[cur_arg], "odd") == 0) {
1583 set |= 0x55555555;
1584 }
1585 else if (strcmp(args[cur_arg], "even") == 0) {
1586 set |= 0xAAAAAAAA;
1587 }
1588 else {
1589 u = str2uic(args[cur_arg]);
1590 if (u < 1 || u > 32) {
1591 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001595 }
1596 if (u > global.nbproc) {
1597 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1598 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001599 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001600 }
1601 set |= 1 << (u - 1);
1602 }
1603 cur_arg++;
1604 }
1605 curproxy->bind_proc = set;
1606 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001607 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001608 if (curproxy == &defproxy) {
1609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001612 }
1613
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001614 err = invalid_char(args[1]);
1615 if (err) {
1616 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1617 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001619 }
1620
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001621 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1622 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1623 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001626 }
1627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1629 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (*(args[1]) == 0) {
1635 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001640
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001641 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001642 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 curproxy->cookie_name = strdup(args[1]);
1644 curproxy->cookie_len = strlen(curproxy->cookie_name);
1645
1646 cur_arg = 2;
1647 while (*(args[cur_arg])) {
1648 if (!strcmp(args[cur_arg], "rewrite")) {
1649 curproxy->options |= PR_O_COOK_RW;
1650 }
1651 else if (!strcmp(args[cur_arg], "indirect")) {
1652 curproxy->options |= PR_O_COOK_IND;
1653 }
1654 else if (!strcmp(args[cur_arg], "insert")) {
1655 curproxy->options |= PR_O_COOK_INS;
1656 }
1657 else if (!strcmp(args[cur_arg], "nocache")) {
1658 curproxy->options |= PR_O_COOK_NOC;
1659 }
1660 else if (!strcmp(args[cur_arg], "postonly")) {
1661 curproxy->options |= PR_O_COOK_POST;
1662 }
1663 else if (!strcmp(args[cur_arg], "prefix")) {
1664 curproxy->options |= PR_O_COOK_PFX;
1665 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001666 else if (!strcmp(args[cur_arg], "domain")) {
1667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1669 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001672 }
1673
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001674 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001675 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001676 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1677 " dots nor does not start with a dot."
1678 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001679 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001680 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001681 }
1682
1683 err = invalid_domainchar(args[cur_arg + 1]);
1684 if (err) {
1685 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1686 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001689 }
1690
Willy Tarreau68a897b2009-12-03 23:28:34 +01001691 if (!curproxy->cookie_domain) {
1692 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1693 } else {
1694 /* one domain was already specified, add another one by
1695 * building the string which will be returned along with
1696 * the cookie.
1697 */
1698 char *new_ptr;
1699 int new_len = strlen(curproxy->cookie_domain) +
1700 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1701 new_ptr = malloc(new_len);
1702 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1703 free(curproxy->cookie_domain);
1704 curproxy->cookie_domain = new_ptr;
1705 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001706 cur_arg++;
1707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001709 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 }
1714 cur_arg++;
1715 }
1716 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1717 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1718 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001719 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 }
1721
1722 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1723 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1724 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 }
1727 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001728 else if (!strcmp(args[0], "persist")) { /* persist */
1729 if (*(args[1]) == 0) {
1730 Alert("parsing [%s:%d] : missing persist method.\n",
1731 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001734 }
1735
1736 if (!strncmp(args[1], "rdp-cookie", 10)) {
1737 curproxy->options2 |= PR_O2_RDPC_PRST;
1738
Emeric Brunb982a3d2010-01-04 15:45:53 +01001739 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001740 const char *beg, *end;
1741
1742 beg = args[1] + 11;
1743 end = strchr(beg, ')');
1744
1745 if (!end || end == beg) {
1746 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_ALERT | ERR_FATAL;
1749 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001750 }
1751
1752 free(curproxy->rdp_cookie_name);
1753 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1754 curproxy->rdp_cookie_len = end-beg;
1755 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001756 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001757 free(curproxy->rdp_cookie_name);
1758 curproxy->rdp_cookie_name = strdup("msts");
1759 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1760 }
1761 else { /* syntax */
1762 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1763 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001766 }
1767 }
1768 else {
1769 Alert("parsing [%s:%d] : unknown persist method.\n",
1770 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001773 }
1774 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001776 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001778 if (curproxy == &defproxy) {
1779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau977b8e42006-12-29 14:19:17 +01001784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001786
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001788 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 }
1793 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001794 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 curproxy->appsession_name = strdup(args[1]);
1796 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1797 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001798 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1799 if (err) {
1800 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1801 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001804 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001805 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001806
Willy Tarreau51041c72007-09-09 21:56:53 +02001807 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1808 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_ALERT | ERR_ABORT;
1810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001812
1813 cur_arg = 6;
1814 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001815 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1816 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001817 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001818 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001819 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001820 } else if (!strcmp(args[cur_arg], "prefix")) {
1821 curproxy->options2 |= PR_O2_AS_PFX;
1822 } else if (!strcmp(args[cur_arg], "mode")) {
1823 if (!*args[cur_arg + 1]) {
1824 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1825 file, linenum, args[0], args[cur_arg]);
1826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
1828 }
1829
1830 cur_arg++;
1831 if (!strcmp(args[cur_arg], "query-string")) {
1832 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1833 curproxy->options2 |= PR_O2_AS_M_QS;
1834 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1836 curproxy->options2 |= PR_O2_AS_M_PP;
1837 } else {
1838 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001843 cur_arg++;
1844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 } /* Url App Session */
1846 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001851 if (curproxy == &defproxy) {
1852 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 if (*(args[4]) == 0) {
1858 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001863 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->capture_name = strdup(args[2]);
1865 curproxy->capture_namelen = strlen(curproxy->capture_name);
1866 curproxy->capture_len = atol(args[4]);
1867 if (curproxy->capture_len >= CAPTURE_LEN) {
1868 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1869 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001870 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->capture_len = CAPTURE_LEN - 1;
1872 }
1873 curproxy->to_log |= LW_COOKIE;
1874 }
1875 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1876 struct cap_hdr *hdr;
1877
1878 if (curproxy == &defproxy) {
1879 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 }
1883
1884 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1885 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1886 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
1890
1891 hdr = calloc(sizeof(struct cap_hdr), 1);
1892 hdr->next = curproxy->req_cap;
1893 hdr->name = strdup(args[3]);
1894 hdr->namelen = strlen(args[3]);
1895 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001896 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 hdr->index = curproxy->nb_req_cap++;
1898 curproxy->req_cap = hdr;
1899 curproxy->to_log |= LW_REQHDR;
1900 }
1901 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1902 struct cap_hdr *hdr;
1903
1904 if (curproxy == &defproxy) {
1905 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909
1910 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1911 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1912 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
1916 hdr = calloc(sizeof(struct cap_hdr), 1);
1917 hdr->next = curproxy->rsp_cap;
1918 hdr->name = strdup(args[3]);
1919 hdr->namelen = strlen(args[3]);
1920 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001921 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 hdr->index = curproxy->nb_rsp_cap++;
1923 curproxy->rsp_cap = hdr;
1924 curproxy->to_log |= LW_RSPHDR;
1925 }
1926 else {
1927 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 if (*(args[1]) == 0) {
1938 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
1943 curproxy->conn_retries = atol(args[1]);
1944 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001945 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1946 struct req_acl_rule *req_acl;
1947
1948 if (curproxy == &defproxy) {
1949 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
1952 }
1953
1954
1955 if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
1956 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1957 file, linenum, args[0]);
1958 err_code |= ERR_WARN;
1959 }
1960
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001961 req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001962
1963 if (!req_acl) {
1964 err_code |= ERR_ALERT | ERR_ABORT;
1965 goto out;
1966 }
1967
Willy Tarreau9cc670f2010-02-01 10:43:44 +01001968 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01001969 LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
1970 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001971 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001972 if (curproxy == &defproxy) {
1973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001976 }
1977
Willy Tarreauef6494c2010-01-28 17:12:36 +01001978 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001979 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1980 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001983 }
1984
Willy Tarreauef6494c2010-01-28 17:12:36 +01001985 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001986 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1987 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001990 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001991
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001992 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001993 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001994 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001995 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 struct redirect_rule *rule;
1997 int cur_arg;
1998 int type = REDIRECT_TYPE_NONE;
1999 int code = 302;
2000 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002001 char *cookie = NULL;
2002 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002003 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002004
Cyril Bonté99ed3272010-01-24 23:29:44 +01002005 if (curproxy == &defproxy) {
2006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
2009 }
2010
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002011 cur_arg = 1;
2012 while (*(args[cur_arg])) {
2013 if (!strcmp(args[cur_arg], "location")) {
2014 if (!*args[cur_arg + 1]) {
2015 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2016 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002019 }
2020
2021 type = REDIRECT_TYPE_LOCATION;
2022 cur_arg++;
2023 destination = args[cur_arg];
2024 }
2025 else if (!strcmp(args[cur_arg], "prefix")) {
2026 if (!*args[cur_arg + 1]) {
2027 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2028 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002031 }
2032
2033 type = REDIRECT_TYPE_PREFIX;
2034 cur_arg++;
2035 destination = args[cur_arg];
2036 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002037 else if (!strcmp(args[cur_arg], "set-cookie")) {
2038 if (!*args[cur_arg + 1]) {
2039 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2040 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002043 }
2044
2045 cur_arg++;
2046 cookie = args[cur_arg];
2047 cookie_set = 1;
2048 }
2049 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2050 if (!*args[cur_arg + 1]) {
2051 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2052 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
2054 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002055 }
2056
2057 cur_arg++;
2058 cookie = args[cur_arg];
2059 cookie_set = 0;
2060 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002061 else if (!strcmp(args[cur_arg],"code")) {
2062 if (!*args[cur_arg + 1]) {
2063 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002067 }
2068 cur_arg++;
2069 code = atol(args[cur_arg]);
2070 if (code < 301 || code > 303) {
2071 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2072 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002075 }
2076 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002077 else if (!strcmp(args[cur_arg],"drop-query")) {
2078 flags |= REDIRECT_FLAG_DROP_QS;
2079 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002080 else if (!strcmp(args[cur_arg],"append-slash")) {
2081 flags |= REDIRECT_FLAG_APPEND_SLASH;
2082 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002083 else if (strcmp(args[cur_arg], "if") == 0 ||
2084 strcmp(args[cur_arg], "unless") == 0) {
2085 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2086 if (!cond) {
2087 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2088 file, linenum, args[0]);
2089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002092 break;
2093 }
2094 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002095 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002096 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002099 }
2100 cur_arg++;
2101 }
2102
2103 if (type == REDIRECT_TYPE_NONE) {
2104 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2105 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002108 }
2109
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002110 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2111 rule->cond = cond;
2112 rule->rdr_str = strdup(destination);
2113 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002114 if (cookie) {
2115 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002116 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002117 */
2118 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002119 if (cookie_set) {
2120 rule->cookie_str = malloc(rule->cookie_len + 10);
2121 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2122 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2123 rule->cookie_len += 9;
2124 } else {
2125 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002126 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002127 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2128 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002129 }
2130 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002131 rule->type = type;
2132 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002133 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002134 LIST_INIT(&rule->list);
2135 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002136 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002137 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002138 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002139 struct switching_rule *rule;
2140
Willy Tarreaub099aca2008-10-12 17:26:37 +02002141 if (curproxy == &defproxy) {
2142 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002145 }
2146
Willy Tarreau55ea7572007-06-17 19:56:27 +02002147 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002149
2150 if (*(args[1]) == 0) {
2151 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002154 }
2155
Willy Tarreauef6494c2010-01-28 17:12:36 +01002156 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002157 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002161 }
2162
Willy Tarreauef6494c2010-01-28 17:12:36 +01002163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002164 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002168 }
2169
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002170 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002171
Willy Tarreau55ea7572007-06-17 19:56:27 +02002172 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2173 rule->cond = cond;
2174 rule->be.name = strdup(args[1]);
2175 LIST_INIT(&rule->list);
2176 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2177 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002178 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002179 struct force_persist_rule *rule;
2180
2181 if (curproxy == &defproxy) {
2182 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186
2187 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2188 err_code |= ERR_WARN;
2189
Willy Tarreauef6494c2010-01-28 17:12:36 +01002190 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002191 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2192 file, linenum, args[0]);
2193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
2195 }
2196
Willy Tarreauef6494c2010-01-28 17:12:36 +01002197 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002198 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2199 file, linenum);
2200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
2203
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002204 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002205
2206 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2207 rule->cond = cond;
2208 LIST_INIT(&rule->list);
2209 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2210 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002211 else if (!strcmp(args[0], "stick-table")) {
2212 int myidx = 1;
2213
2214 curproxy->table.type = (unsigned int)-1;
2215 while (*args[myidx]) {
2216 const char *err;
2217
2218 if (strcmp(args[myidx], "size") == 0) {
2219 myidx++;
2220 if (!*(args[myidx])) {
2221 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2222 file, linenum, args[myidx-1]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2227 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2228 file, linenum, *err, args[myidx-1]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002233 }
2234 else if (strcmp(args[myidx], "expire") == 0) {
2235 myidx++;
2236 if (!*(args[myidx])) {
2237 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2238 file, linenum, args[myidx-1]);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2243 if (err) {
2244 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2245 file, linenum, *err, args[myidx-1]);
2246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
2248 }
2249 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002250 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002251 }
2252 else if (strcmp(args[myidx], "nopurge") == 0) {
2253 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002254 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002255 }
2256 else if (strcmp(args[myidx], "type") == 0) {
2257 myidx++;
2258 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2259 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2260 file, linenum, args[myidx]);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002264 /* myidx already points to next arg */
2265 }
2266 else {
2267 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2268 file, linenum, args[myidx]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002271 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002272 }
2273
2274 if (!curproxy->table.size) {
2275 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2276 file, linenum);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
2281 if (curproxy->table.type == (unsigned int)-1) {
2282 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2283 file, linenum);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287 }
2288 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002289 struct sticking_rule *rule;
2290 struct pattern_expr *expr;
2291 int myidx = 0;
2292 const char *name = NULL;
2293 int flags;
2294
2295 if (curproxy == &defproxy) {
2296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
2299 }
2300
2301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2302 err_code |= ERR_WARN;
2303 goto out;
2304 }
2305
2306 myidx++;
2307 if ((strcmp(args[myidx], "store") == 0) ||
2308 (strcmp(args[myidx], "store-request") == 0)) {
2309 myidx++;
2310 flags = STK_IS_STORE;
2311 }
2312 else if (strcmp(args[myidx], "store-response") == 0) {
2313 myidx++;
2314 flags = STK_IS_STORE | STK_ON_RSP;
2315 }
2316 else if (strcmp(args[myidx], "match") == 0) {
2317 myidx++;
2318 flags = STK_IS_MATCH;
2319 }
2320 else if (strcmp(args[myidx], "on") == 0) {
2321 myidx++;
2322 flags = STK_IS_MATCH | STK_IS_STORE;
2323 }
2324 else {
2325 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
2330 if (*(args[myidx]) == 0) {
2331 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
2336 expr = pattern_parse_expr(args, &myidx);
2337 if (!expr) {
2338 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342
2343 if (flags & STK_ON_RSP) {
2344 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2345 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2346 file, linenum, args[0], expr->fetch->kw);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 } else {
2351 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2352 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2353 file, linenum, args[0], expr->fetch->kw);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357 }
2358
2359 if (strcmp(args[myidx], "table") == 0) {
2360 myidx++;
2361 name = args[myidx++];
2362 }
2363
Willy Tarreauef6494c2010-01-28 17:12:36 +01002364 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2365 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002366 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2367 file, linenum, args[0]);
2368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
2370 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002371 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002372 else if (*(args[myidx])) {
2373 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2374 file, linenum, args[0], args[myidx]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002379 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2380
Emeric Brunb982a3d2010-01-04 15:45:53 +01002381 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2382 rule->cond = cond;
2383 rule->expr = expr;
2384 rule->flags = flags;
2385 rule->table.name = name ? strdup(name) : NULL;
2386 LIST_INIT(&rule->list);
2387 if (flags & STK_ON_RSP)
2388 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2389 else
2390 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002395
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2397 curproxy->uri_auth = NULL; /* we must detach from the default config */
2398
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002399 if (!*args[1]) {
2400 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 } else if (!strcmp(args[1], "uri")) {
2402 if (*(args[2]) == 0) {
2403 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2407 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_ABORT;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411 } else if (!strcmp(args[1], "realm")) {
2412 if (*(args[2]) == 0) {
2413 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2417 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_ABORT;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002421 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002422 unsigned interval;
2423
2424 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2425 if (err) {
2426 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2427 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002430 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_ABORT;
2433 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002434 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002435 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
2436 struct req_acl_rule *req_acl;
2437
2438 if (curproxy == &defproxy) {
2439 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
2444 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2445 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2446 err_code |= ERR_ALERT | ERR_ABORT;
2447 goto out;
2448 }
2449
2450 if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
2451 !LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
2452 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2453 file, linenum, args[0]);
2454 err_code |= ERR_WARN;
2455 }
2456
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002457 req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002458
2459 if (!req_acl) {
2460 err_code |= ERR_ALERT | ERR_ABORT;
2461 goto out;
2462 }
2463
Willy Tarreau9cc670f2010-02-01 10:43:44 +01002464 err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002465 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
2466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 } else if (!strcmp(args[1], "auth")) {
2468 if (*(args[2]) == 0) {
2469 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2473 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_ABORT;
2475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 }
2477 } else if (!strcmp(args[1], "scope")) {
2478 if (*(args[2]) == 0) {
2479 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2483 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_ABORT;
2485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }
2487 } else if (!strcmp(args[1], "enable")) {
2488 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2489 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_ABORT;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002493 } else if (!strcmp(args[1], "hide-version")) {
2494 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_ABORT;
2497 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002498 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002499 } else if (!strcmp(args[1], "show-legends")) {
2500 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2501 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2502 err_code |= ERR_ALERT | ERR_ABORT;
2503 goto out;
2504 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002505 } else if (!strcmp(args[1], "show-node")) {
2506
2507 if (*args[2]) {
2508 int i;
2509 char c;
2510
2511 for (i=0; args[2][i]; i++) {
2512 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01002513 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
2514 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002515 break;
2516 }
2517
2518 if (!i || args[2][i]) {
2519 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2520 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2521 file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 }
2526
2527 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2528 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2529 err_code |= ERR_ALERT | ERR_ABORT;
2530 goto out;
2531 }
2532 } else if (!strcmp(args[1], "show-desc")) {
2533 char *desc = NULL;
2534
2535 if (*args[2]) {
2536 int i, len=0;
2537 char *d;
2538
2539 for(i=2; *args[i]; i++)
2540 len += strlen(args[i])+1;
2541
2542 desc = d = (char *)calloc(1, len);
2543
2544 d += sprintf(d, "%s", args[2]);
2545 for(i=3; *args[i]; i++)
2546 d += sprintf(d, " %s", args[i]);
2547 }
2548
2549 if (!*args[2] && !global.desc)
2550 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2551 file, linenum, args[1]);
2552 else {
2553 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2554 free(desc);
2555 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2556 err_code |= ERR_ALERT | ERR_ABORT;
2557 goto out;
2558 }
2559 free(desc);
2560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002562stats_error_parsing:
2563 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2564 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
2568 }
2569 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002570 int optnum;
2571
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002572 if (*(args[1]) == '\0') {
2573 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002578
2579 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2580 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002581 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2582 err_code |= ERR_WARN;
2583 goto out;
2584 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002585
Willy Tarreau3842f002009-06-14 11:39:52 +02002586 curproxy->no_options &= ~cfg_opts[optnum].val;
2587 curproxy->options &= ~cfg_opts[optnum].val;
2588
2589 switch (kwm) {
2590 case KWM_STD:
2591 curproxy->options |= cfg_opts[optnum].val;
2592 break;
2593 case KWM_NO:
2594 curproxy->no_options |= cfg_opts[optnum].val;
2595 break;
2596 case KWM_DEF: /* already cleared */
2597 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002598 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002599
Willy Tarreau93893792009-07-23 13:19:11 +02002600 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002601 }
2602 }
2603
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002604 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2605 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002606 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2607 err_code |= ERR_WARN;
2608 goto out;
2609 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002610
Willy Tarreau3842f002009-06-14 11:39:52 +02002611 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2612 curproxy->options2 &= ~cfg_opts2[optnum].val;
2613
2614 switch (kwm) {
2615 case KWM_STD:
2616 curproxy->options2 |= cfg_opts2[optnum].val;
2617 break;
2618 case KWM_NO:
2619 curproxy->no_options2 |= cfg_opts2[optnum].val;
2620 break;
2621 case KWM_DEF: /* already cleared */
2622 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002623 }
Willy Tarreau93893792009-07-23 13:19:11 +02002624 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002625 }
2626 }
2627
Willy Tarreau3842f002009-06-14 11:39:52 +02002628 if (kwm != KWM_STD) {
2629 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002630 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002633 }
2634
Emeric Brun3a058f32009-06-30 18:26:00 +02002635 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002637 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002639 if (*(args[2]) != '\0') {
2640 if (!strcmp(args[2], "clf")) {
2641 curproxy->options2 |= PR_O2_CLFLOG;
2642 } else {
2643 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002646 }
2647 }
2648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else if (!strcmp(args[1], "tcplog"))
2650 /* generate a detailed TCP log */
2651 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 else if (!strcmp(args[1], "tcpka")) {
2653 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002654 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002656
2657 if (curproxy->cap & PR_CAP_FE)
2658 curproxy->options |= PR_O_TCP_CLI_KA;
2659 if (curproxy->cap & PR_CAP_BE)
2660 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 }
2662 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002663 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_WARN;
2665
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002667 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002668 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002669 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002670 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002671 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002672 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 if (!*args[2]) { /* no argument */
2674 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2675 curproxy->check_len = strlen(DEF_CHECK_REQ);
2676 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002677 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 curproxy->check_req = (char *)malloc(reqlen);
2679 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002680 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002682 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 if (*args[4])
2684 reqlen += strlen(args[4]);
2685 else
2686 reqlen += strlen("HTTP/1.0");
2687
2688 curproxy->check_req = (char *)malloc(reqlen);
2689 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002690 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002692 }
2693 else if (!strcmp(args[1], "ssl-hello-chk")) {
2694 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002695 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002697
Willy Tarreaua534fea2008-08-03 12:19:50 +02002698 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002699 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002700 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002701 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002702 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002703 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 }
Willy Tarreau23677902007-05-08 23:50:35 +02002705 else if (!strcmp(args[1], "smtpchk")) {
2706 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002707 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002708 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02002709 curproxy->options &= ~PR_O_HTTP_CHK;
2710 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002711 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002712 curproxy->options |= PR_O_SMTP_CHK;
2713
2714 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2715 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2716 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2717 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2718 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2719 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2720 curproxy->check_req = (char *)malloc(reqlen);
2721 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2722 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2723 } else {
2724 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2725 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2726 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2727 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2728 }
2729 }
2730 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002731 else if (!strcmp(args[1], "mysql-check")) {
2732 /* use MYSQL request to check servers' health */
2733 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01002734 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002735 curproxy->options &= ~PR_O_HTTP_CHK;
2736 curproxy->options &= ~PR_O_SSL3_CHK;
2737 curproxy->options &= ~PR_O_SMTP_CHK;
2738 curproxy->options2 |= PR_O2_MYSQL_CHK;
2739 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002740 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002741 int cur_arg;
2742
2743 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2744 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002745 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002746
2747 curproxy->options |= PR_O_FWDFOR;
2748
2749 free(curproxy->fwdfor_hdr_name);
2750 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2751 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2752
2753 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2754 cur_arg = 2;
2755 while (*(args[cur_arg])) {
2756 if (!strcmp(args[cur_arg], "except")) {
2757 /* suboption except - needs additional argument for it */
2758 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2759 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2760 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002763 }
2764 /* flush useless bits */
2765 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002766 cur_arg += 2;
2767 } else if (!strcmp(args[cur_arg], "header")) {
2768 /* suboption header - needs additional argument for it */
2769 if (*(args[cur_arg+1]) == 0) {
2770 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2771 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002774 }
2775 free(curproxy->fwdfor_hdr_name);
2776 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2777 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2778 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002779 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002780 /* unknown suboption - catchall */
2781 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2782 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002785 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002786 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002787 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002788 else if (!strcmp(args[1], "originalto")) {
2789 int cur_arg;
2790
2791 /* insert x-original-to field, but not for the IP address listed as an except.
2792 * set default options (ie: bitfield, header name, etc)
2793 */
2794
2795 curproxy->options |= PR_O_ORGTO;
2796
2797 free(curproxy->orgto_hdr_name);
2798 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2799 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2800
2801 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2802 cur_arg = 2;
2803 while (*(args[cur_arg])) {
2804 if (!strcmp(args[cur_arg], "except")) {
2805 /* suboption except - needs additional argument for it */
2806 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2807 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2808 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002811 }
2812 /* flush useless bits */
2813 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2814 cur_arg += 2;
2815 } else if (!strcmp(args[cur_arg], "header")) {
2816 /* suboption header - needs additional argument for it */
2817 if (*(args[cur_arg+1]) == 0) {
2818 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2819 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002822 }
2823 free(curproxy->orgto_hdr_name);
2824 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2825 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2826 cur_arg += 2;
2827 } else {
2828 /* unknown suboption - catchall */
2829 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2830 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002833 }
2834 } /* end while loop */
2835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002836 else {
2837 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
Willy Tarreau93893792009-07-23 13:19:11 +02002841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002843 else if (!strcmp(args[0], "default_backend")) {
2844 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002846
2847 if (*(args[1]) == 0) {
2848 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002851 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002852 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002853 curproxy->defbe.name = strdup(args[1]);
2854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002858
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002859 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2860 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002861 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 /* enable reconnections to dispatch */
2863 curproxy->options |= PR_O_REDISP;
2864 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002865 else if (!strcmp(args[0], "http-check")) {
2866 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002867 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002868
2869 if (strcmp(args[1], "disable-on-404") == 0) {
2870 /* enable a graceful server shutdown on an HTTP 404 response */
2871 curproxy->options |= PR_O_DISABLE404;
2872 }
Willy Tarreauef781042010-01-27 11:53:01 +01002873 else if (strcmp(args[1], "send-state") == 0) {
2874 /* enable emission of the apparent state of a server in HTTP checks */
2875 curproxy->options2 |= PR_O2_CHK_SNDST;
2876 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002877 else {
2878 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002881 }
2882 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002883 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002884 if (curproxy == &defproxy) {
2885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002888 }
2889
Willy Tarreaub80c2302007-11-30 20:51:32 +01002890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002892
2893 if (strcmp(args[1], "fail") == 0) {
2894 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002895 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002896 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2897 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002900 }
2901
Willy Tarreauef6494c2010-01-28 17:12:36 +01002902 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002903 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2904 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002907 }
2908 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2909 }
2910 else {
2911 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002914 }
2915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916#ifdef TPROXY
2917 else if (!strcmp(args[0], "transparent")) {
2918 /* enable transparent proxy connections */
2919 curproxy->options |= PR_O_TRANSP;
2920 }
2921#endif
2922 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 }
2931 curproxy->maxconn = atol(args[1]);
2932 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002933 else if (!strcmp(args[0], "backlog")) { /* backlog */
2934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002936
2937 if (*(args[1]) == 0) {
2938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002941 }
2942 curproxy->backlog = atol(args[1]);
2943 }
Willy Tarreau86034312006-12-29 00:10:33 +01002944 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002947
Willy Tarreau86034312006-12-29 00:10:33 +01002948 if (*(args[1]) == 0) {
2949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002952 }
2953 curproxy->fullconn = atol(args[1]);
2954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2956 if (*(args[1]) == 0) {
2957 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002961 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2962 if (err) {
2963 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2964 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002967 }
2968 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 }
2970 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
Willy Tarreaud5191e72010-02-09 20:50:45 +01002971 struct sockaddr_in *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 if (curproxy == &defproxy) {
2973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002977 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 if (strchr(args[1], ':') == NULL) {
2981 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002984 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01002985 sk = str2sa(args[1]);
2986 if (!sk) {
2987 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 curproxy->dispatch_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 }
2993 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002996
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002997 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002998 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2999 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003004 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3005 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3006 err_code |= ERR_WARN;
3007
3008 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3009 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3010 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3011 }
3012 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3013 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3014 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3015 }
3016 else {
3017 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003022 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003024 char *rport, *raddr;
3025 short realport = 0;
3026 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003028 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003033 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035
3036 if (!*args[2]) {
3037 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003042
3043 err = invalid_char(args[1]);
3044 if (err) {
3045 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3046 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003049 }
3050
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003051 if (!defsrv) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003052 struct sockaddr_in *sk;
3053
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003054 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3055 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3056 err_code |= ERR_ALERT | ERR_ABORT;
3057 goto out;
3058 }
3059
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003060 /* the servers are linked backwards first */
3061 newsrv->next = curproxy->srv;
3062 curproxy->srv = newsrv;
3063 newsrv->proxy = curproxy;
3064 newsrv->conf.file = file;
3065 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003067 LIST_INIT(&newsrv->pendconns);
3068 do_check = 0;
3069 newsrv->state = SRV_RUNNING; /* early server setup */
3070 newsrv->last_change = now.tv_sec;
3071 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003073 /* several ways to check the port component :
3074 * - IP => port=+0, relative
3075 * - IP: => port=+0, relative
3076 * - IP:N => port=N, absolute
3077 * - IP:+N => port=+N, relative
3078 * - IP:-N => port=-N, relative
3079 */
3080 raddr = strdup(args[2]);
3081 rport = strchr(raddr, ':');
3082 if (rport) {
3083 *rport++ = 0;
3084 realport = atol(rport);
3085 if (!isdigit((unsigned char)*rport))
3086 newsrv->state |= SRV_MAPPORTS;
3087 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003089
Willy Tarreaud5191e72010-02-09 20:50:45 +01003090 sk = str2sa(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003091 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003092 if (!sk) {
3093 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097 newsrv->addr = *sk;
3098 newsrv->addr.sin_port = htons(realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003099
3100 newsrv->check_port = curproxy->defsrv.check_port;
3101 newsrv->inter = curproxy->defsrv.inter;
3102 newsrv->fastinter = curproxy->defsrv.fastinter;
3103 newsrv->downinter = curproxy->defsrv.downinter;
3104 newsrv->rise = curproxy->defsrv.rise;
3105 newsrv->fall = curproxy->defsrv.fall;
3106 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3107 newsrv->minconn = curproxy->defsrv.minconn;
3108 newsrv->maxconn = curproxy->defsrv.maxconn;
3109 newsrv->slowstart = curproxy->defsrv.slowstart;
3110 newsrv->onerror = curproxy->defsrv.onerror;
3111 newsrv->consecutive_errors_limit
3112 = curproxy->defsrv.consecutive_errors_limit;
3113 newsrv->uweight = newsrv->iweight
3114 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003116 newsrv->curfd = -1; /* no health-check in progress */
3117 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118
Nick Chalk57b1bf72010-03-16 15:50:46 +00003119 /* Allocate buffer for partial check results... */
3120 if ((newsrv->check_data = calloc(BUFSIZE, sizeof(char))) == NULL) {
3121 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
3122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
3124 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003125 cur_arg = 3;
3126 } else {
3127 newsrv = &curproxy->defsrv;
3128 cur_arg = 1;
3129 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003130
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003132 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003133 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003134
3135 if (!*args[cur_arg + 1]) {
3136 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3137 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003140 }
3141
3142 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003143 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003144
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003145 if (newsrv->puid <= 0) {
3146 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003147 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003150 }
3151
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003152 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3153 if (node) {
3154 struct server *target = container_of(node, struct server, conf.id);
3155 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3156 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
3159 }
3160 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003161 cur_arg += 2;
3162 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003163 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 newsrv->cookie = strdup(args[cur_arg + 1]);
3165 newsrv->cklen = strlen(args[cur_arg + 1]);
3166 cur_arg += 2;
3167 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003168 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003169 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3170 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3171 cur_arg += 2;
3172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003174 if (!*args[cur_arg + 1]) {
3175 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3176 file, linenum, args[cur_arg]);
3177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
3180
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003182 if (newsrv->rise <= 0) {
3183 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3184 file, linenum, args[cur_arg]);
3185 err_code |= ERR_ALERT | ERR_FATAL;
3186 goto out;
3187 }
3188
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 newsrv->health = newsrv->rise;
3190 cur_arg += 2;
3191 }
3192 else if (!strcmp(args[cur_arg], "fall")) {
3193 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003194
3195 if (!*args[cur_arg + 1]) {
3196 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3197 file, linenum, args[cur_arg]);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
3201
3202 if (newsrv->fall <= 0) {
3203 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3204 file, linenum, args[cur_arg]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
3207 }
3208
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 cur_arg += 2;
3210 }
3211 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003212 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3213 if (err) {
3214 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3215 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003218 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003219 if (val <= 0) {
3220 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3221 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003224 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003225 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 cur_arg += 2;
3227 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003228 else if (!strcmp(args[cur_arg], "fastinter")) {
3229 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3230 if (err) {
3231 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3232 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003235 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003236 if (val <= 0) {
3237 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3238 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003241 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003242 newsrv->fastinter = val;
3243 cur_arg += 2;
3244 }
3245 else if (!strcmp(args[cur_arg], "downinter")) {
3246 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3247 if (err) {
3248 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3249 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003252 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003253 if (val <= 0) {
3254 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3255 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003258 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003259 newsrv->downinter = val;
3260 cur_arg += 2;
3261 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003262 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003263 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3264 if (!sk) {
3265 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003270 cur_arg += 2;
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 else if (!strcmp(args[cur_arg], "port")) {
3273 newsrv->check_port = atol(args[cur_arg + 1]);
3274 cur_arg += 2;
3275 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003276 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 newsrv->state |= SRV_BACKUP;
3278 cur_arg ++;
3279 }
3280 else if (!strcmp(args[cur_arg], "weight")) {
3281 int w;
3282 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003283 if (w < 0 || w > 256) {
3284 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003289 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 cur_arg += 2;
3291 }
3292 else if (!strcmp(args[cur_arg], "minconn")) {
3293 newsrv->minconn = atol(args[cur_arg + 1]);
3294 cur_arg += 2;
3295 }
3296 else if (!strcmp(args[cur_arg], "maxconn")) {
3297 newsrv->maxconn = atol(args[cur_arg + 1]);
3298 cur_arg += 2;
3299 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003300 else if (!strcmp(args[cur_arg], "maxqueue")) {
3301 newsrv->maxqueue = atol(args[cur_arg + 1]);
3302 cur_arg += 2;
3303 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003304 else if (!strcmp(args[cur_arg], "slowstart")) {
3305 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003306 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003307 if (err) {
3308 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3309 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003312 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003313 if (val <= 0) {
3314 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3315 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_FATAL;
3317 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003318 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003319 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003320 cur_arg += 2;
3321 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003322 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003323
3324 if (!*args[cur_arg + 1]) {
3325 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3326 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003329 }
3330
3331 newsrv->trackit = strdup(args[cur_arg + 1]);
3332
3333 cur_arg += 2;
3334 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003335 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 global.maxsock++;
3337 do_check = 1;
3338 cur_arg += 1;
3339 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003340 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003341 if (!strcmp(args[cur_arg + 1], "none"))
3342 newsrv->observe = HANA_OBS_NONE;
3343 else if (!strcmp(args[cur_arg + 1], "layer4"))
3344 newsrv->observe = HANA_OBS_LAYER4;
3345 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3346 if (curproxy->mode != PR_MODE_HTTP) {
3347 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3348 file, linenum, args[cur_arg + 1]);
3349 err_code |= ERR_ALERT;
3350 }
3351 newsrv->observe = HANA_OBS_LAYER7;
3352 }
3353 else {
3354 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3355 "'l4events', 'http-responses' but get '%s'\n",
3356 file, linenum, args[cur_arg], args[cur_arg + 1]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 cur_arg += 2;
3362 }
3363 else if (!strcmp(args[cur_arg], "on-error")) {
3364 if (!strcmp(args[cur_arg + 1], "fastinter"))
3365 newsrv->onerror = HANA_ONERR_FASTINTER;
3366 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3367 newsrv->onerror = HANA_ONERR_FAILCHK;
3368 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3369 newsrv->onerror = HANA_ONERR_SUDDTH;
3370 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3371 newsrv->onerror = HANA_ONERR_MARKDWN;
3372 else {
3373 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3374 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3375 file, linenum, args[cur_arg], args[cur_arg + 1]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
3379
3380 cur_arg += 2;
3381 }
3382 else if (!strcmp(args[cur_arg], "error-limit")) {
3383 if (!*args[cur_arg + 1]) {
3384 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3385 file, linenum, args[cur_arg]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389
3390 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3391
3392 if (newsrv->consecutive_errors_limit <= 0) {
3393 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3394 file, linenum, args[cur_arg]);
3395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
3397 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01003398 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003399 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003400 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003401 int port_low, port_high;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003402 struct sockaddr_in *sk;
3403
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003405#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003406 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003407 file, linenum, "source", "usesrc");
3408#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003409 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003411#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 }
3415 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003416 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3417 if (!sk) {
3418 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003423
3424 if (port_low != port_high) {
3425 int i;
3426 if (port_low <= 0 || port_low > 65535 ||
3427 port_high <= 0 || port_high > 65535 ||
3428 port_low > port_high) {
3429 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3430 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003433 }
3434 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3435 for (i = 0; i < newsrv->sport_range->size; i++)
3436 newsrv->sport_range->ports[i] = port_low + i;
3437 }
3438
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003440 while (*(args[cur_arg])) {
3441 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003442#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3443#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003444 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3445 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3446 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003449 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003450#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003451 if (!*args[cur_arg + 1]) {
3452 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3453 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003456 }
3457 if (!strcmp(args[cur_arg + 1], "client")) {
3458 newsrv->state |= SRV_TPROXY_CLI;
3459 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3460 newsrv->state |= SRV_TPROXY_CIP;
3461 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003462 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3463 if (!sk) {
3464 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003469 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003470 }
3471 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003472#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003473 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003474#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003475 cur_arg += 2;
3476 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003477#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003478 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003479 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003482#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3483 } /* "usesrc" */
3484
3485 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3486#ifdef SO_BINDTODEVICE
3487 if (!*args[cur_arg + 1]) {
3488 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003492 }
3493 if (newsrv->iface_name)
3494 free(newsrv->iface_name);
3495
3496 newsrv->iface_name = strdup(args[cur_arg + 1]);
3497 newsrv->iface_len = strlen(newsrv->iface_name);
3498 global.last_checks |= LSTCHK_NETADM;
3499#else
3500 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3501 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003504#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003505 cur_arg += 2;
3506 continue;
3507 }
3508 /* this keyword in not an option of "source" */
3509 break;
3510 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003512 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003513 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3514 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003519 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003520 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 +01003521 file, linenum, newsrv->id);
3522 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003523 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 +01003524 file, linenum);
3525
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
3529 }
3530
3531 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003532 if (newsrv->trackit) {
3533 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003537 }
3538
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003539 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3540 newsrv->check_port = newsrv->check_addr.sin_port;
3541
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3543 newsrv->check_port = realport; /* by default */
3544 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003545 /* not yet valid, because no port was set on
3546 * the server either. We'll check if we have
3547 * a known port on the first listener.
3548 */
3549 struct listener *l;
3550 l = curproxy->listen;
3551 if (l) {
3552 int port;
3553 port = (l->addr.ss_family == AF_INET6)
3554 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3555 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3556 newsrv->check_port = port;
3557 }
3558 }
3559 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3561 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003565
3566 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 newsrv->state |= SRV_CHECKED;
3568 }
3569
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003570 if (!defsrv) {
3571 if (newsrv->state & SRV_BACKUP)
3572 curproxy->srv_bck++;
3573 else
3574 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003575
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003576 newsrv->prev_state = newsrv->state;
3577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
3579 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003580 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 int facility;
3582
3583 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3584 curproxy->logfac1 = global.logfac1;
3585 curproxy->logsrv1 = global.logsrv1;
3586 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003587 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 curproxy->logfac2 = global.logfac2;
3589 curproxy->logsrv2 = global.logsrv2;
3590 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003591 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 }
3593 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003594 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595
3596 facility = get_log_facility(args[2]);
3597 if (facility < 0) {
3598 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3599 exit(1);
3600 }
3601
3602 level = 7; /* max syslog level = debug */
3603 if (*(args[3])) {
3604 level = get_log_level(args[3]);
3605 if (level < 0) {
3606 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3607 exit(1);
3608 }
3609 }
3610
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003611 minlvl = 0; /* limit syslog level to this level (emerg) */
3612 if (*(args[4])) {
3613 minlvl = get_log_level(args[4]);
3614 if (level < 0) {
3615 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3616 exit(1);
3617 }
3618 }
3619
Robert Tsai81ae1952007-12-05 10:47:29 +01003620 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003621 struct sockaddr_un *sk = str2sun(args[1]);
3622 if (!sk) {
3623 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
3624 args[1], (int)sizeof(sk->sun_path) - 1);
3625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
3627 }
3628 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003629 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01003630 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003631 struct sockaddr_in *sk = str2sa(args[1]);
3632 if (!sk) {
3633 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637 logsrv.u.in = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01003638 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01003639 if (!logsrv.u.in.sin_port) {
3640 logsrv.u.in.sin_port =
3641 htons(SYSLOG_PORT);
3642 }
3643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644
3645 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003646 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 curproxy->logfac1 = facility;
3648 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003649 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003652 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 curproxy->logfac2 = facility;
3654 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003655 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
3657 else {
3658 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
3662 }
3663 else {
3664 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3665 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
3669 }
3670 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003671 int cur_arg;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003672 struct sockaddr_in *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003673
Willy Tarreau977b8e42006-12-29 14:19:17 +01003674 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003676
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003678 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3679 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003683
3684 /* we must first clear any optional default setting */
3685 curproxy->options &= ~PR_O_TPXY_MASK;
3686 free(curproxy->iface_name);
3687 curproxy->iface_name = NULL;
3688 curproxy->iface_len = 0;
3689
Willy Tarreaud5191e72010-02-09 20:50:45 +01003690 sk = str2sa(args[1]);
3691 if (!sk) {
3692 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
3695 }
3696 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003698
3699 cur_arg = 2;
3700 while (*(args[cur_arg])) {
3701 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003702#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3703#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003704 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3705 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3706 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003709 }
3710#endif
3711 if (!*args[cur_arg + 1]) {
3712 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3713 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003716 }
3717
3718 if (!strcmp(args[cur_arg + 1], "client")) {
3719 curproxy->options |= PR_O_TPXY_CLI;
3720 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3721 curproxy->options |= PR_O_TPXY_CIP;
3722 } else {
Willy Tarreaud5191e72010-02-09 20:50:45 +01003723 struct sockaddr_in *sk = str2sa(args[cur_arg + 1]);
3724 if (!sk) {
3725 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
3729 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003730 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003731 }
3732 global.last_checks |= LSTCHK_NETADM;
3733#if !defined(CONFIG_HAP_LINUX_TPROXY)
3734 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003735#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003736#else /* no TPROXY support */
3737 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003738 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003741#endif
3742 cur_arg += 2;
3743 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003744 }
3745
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003746 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3747#ifdef SO_BINDTODEVICE
3748 if (!*args[cur_arg + 1]) {
3749 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3750 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003753 }
3754 if (curproxy->iface_name)
3755 free(curproxy->iface_name);
3756
3757 curproxy->iface_name = strdup(args[cur_arg + 1]);
3758 curproxy->iface_len = strlen(curproxy->iface_name);
3759 global.last_checks |= LSTCHK_NETADM;
3760#else
3761 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3762 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003765#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003766 cur_arg += 2;
3767 continue;
3768 }
3769 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3770 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003775 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3776 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3777 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003782 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003788
3789 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3790 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003791 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003792 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 }
3795 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003796 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3797 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003798 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003799 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
3802 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003803 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3804 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003805 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003806 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
3809 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003810 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3811 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003812 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003813 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 }
3816 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003817 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3818 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003819 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003820 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003823 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003824 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3825 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003826 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003827 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003828 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003829 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003830 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003831 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3832 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003833 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003834 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003835 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003836 }
3837 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003838 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3839 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003840 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003841 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003842 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003845 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3847 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003851
3852 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3853 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003854 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003855 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
3858 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003859 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3860 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003861 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003862 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 }
3865 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003866 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3867 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003868 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003869 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 }
3872 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003873 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3874 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003875 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003876 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
3879 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003880 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3881 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003882 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003883 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003886 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003887 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3888 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003889 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003890 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003891 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003894 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003895
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 if (curproxy == &defproxy) {
3897 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003901 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 if (*(args[1]) == 0) {
3905 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003909
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003910 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3911 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3912 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3913 file, linenum, args[0]);
3914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
3916 }
3917 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3918 }
3919 else if (*args[2]) {
3920 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3921 file, linenum, args[0], args[2]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003926 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003927 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003928 wl->s = strdup(args[1]);
3929 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003930 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
3932 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003933 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3935 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003939
Willy Tarreauade5ec42010-01-28 19:33:49 +01003940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3941 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003942 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 }
3946 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3948 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 }
3953 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3955 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
3960 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003961 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3963 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966 }
3967
Willy Tarreauade5ec42010-01-28 19:33:49 +01003968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3969 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003970 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
3974 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3976 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003977 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 }
3981 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3983 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 }
3988 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003989 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003990
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 if (curproxy == &defproxy) {
3992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003996 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 if (*(args[1]) == 0) {
4000 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 }
4004
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004005 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4006 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4007 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4008 file, linenum, args[0]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012 err_code |= warnif_cond_requires_req(cond, file, linenum);
4013 }
4014 else if (*args[2]) {
4015 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4016 file, linenum, args[0], args[2]);
4017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
4019 }
4020
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004021 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004022 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004023 wl->s = strdup(args[1]);
4024 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 }
4026 else if (!strcmp(args[0], "errorloc") ||
4027 !strcmp(args[0], "errorloc302") ||
4028 !strcmp(args[0], "errorloc303")) { /* error location */
4029 int errnum, errlen;
4030 char *err;
4031
Willy Tarreau977b8e42006-12-29 14:19:17 +01004032 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004036 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 }
4040
4041 errnum = atol(args[1]);
4042 if (!strcmp(args[0], "errorloc303")) {
4043 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4044 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4045 } else {
4046 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4047 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4048 }
4049
Willy Tarreau0f772532006-12-23 20:51:41 +01004050 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4051 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004052 chunk_destroy(&curproxy->errmsg[rc]);
4053 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004054 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004057
4058 if (rc >= HTTP_ERR_SIZE) {
4059 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4060 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 free(err);
4062 }
4063 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004064 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4065 int errnum, errlen, fd;
4066 char *err;
4067 struct stat stat;
4068
4069 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004071
4072 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004073 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004076 }
4077
4078 fd = open(args[2], O_RDONLY);
4079 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4080 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4081 file, linenum, args[2], args[1]);
4082 if (fd >= 0)
4083 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004086 }
4087
Willy Tarreau27a674e2009-08-17 07:23:33 +02004088 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004089 errlen = stat.st_size;
4090 } else {
4091 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004092 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004094 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004095 }
4096
4097 err = malloc(errlen); /* malloc() must succeed during parsing */
4098 errnum = read(fd, err, errlen);
4099 if (errnum != errlen) {
4100 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4101 file, linenum, args[2], args[1]);
4102 close(fd);
4103 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004106 }
4107 close(fd);
4108
4109 errnum = atol(args[1]);
4110 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4111 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004112 chunk_destroy(&curproxy->errmsg[rc]);
4113 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004114 break;
4115 }
4116 }
4117
4118 if (rc >= HTTP_ERR_SIZE) {
4119 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4120 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004122 free(err);
4123 }
4124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004126 struct cfg_kw_list *kwl;
4127 int index;
4128
4129 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4130 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4131 if (kwl->kw[index].section != CFG_LISTEN)
4132 continue;
4133 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4134 /* prepare error message just in case */
4135 snprintf(trash, sizeof(trash),
4136 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004137 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4138 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004139 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004142 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004143 else if (rc > 0) {
4144 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_WARN;
4146 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004147 }
Willy Tarreau93893792009-07-23 13:19:11 +02004148 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004149 }
4150 }
4151 }
4152
Willy Tarreau6daf3432008-01-22 16:44:08 +01004153 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
Willy Tarreau93893792009-07-23 13:19:11 +02004157 out:
4158 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159}
4160
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004161int
4162cfg_parse_users(const char *file, int linenum, char **args, int kwm)
4163{
4164
4165 int err_code = 0;
4166 const char *err;
4167
4168 if (!strcmp(args[0], "userlist")) { /* new userlist */
4169 struct userlist *newul;
4170
4171 if (!*args[1]) {
4172 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4173 file, linenum, args[0]);
4174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
4176 }
4177
4178 err = invalid_char(args[1]);
4179 if (err) {
4180 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4181 file, linenum, *err, args[0], args[1]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
4186 for (newul = userlist; newul; newul = newul->next)
4187 if (!strcmp(newul->name, args[1])) {
4188 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
4189 file, linenum, args[1]);
4190 err_code |= ERR_WARN;
4191 goto out;
4192 }
4193
4194 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
4195 if (!newul) {
4196 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4197 err_code |= ERR_ALERT | ERR_ABORT;
4198 goto out;
4199 }
4200
4201 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
4202 newul->name = strdup(args[1]);
4203
4204 if (!newul->groupusers | !newul->name) {
4205 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4206 err_code |= ERR_ALERT | ERR_ABORT;
4207 goto out;
4208 }
4209
4210 newul->next = userlist;
4211 userlist = newul;
4212
4213 } else if (!strcmp(args[0], "group")) { /* new group */
4214 int cur_arg, i;
4215 const char *err;
4216
4217 if (!*args[1]) {
4218 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4219 file, linenum, args[0]);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223
4224 err = invalid_char(args[1]);
4225 if (err) {
4226 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
4227 file, linenum, *err, args[0], args[1]);
4228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
4230 }
4231
4232 for(i = 0; i < userlist->grpcnt; i++)
4233 if (!strcmp(userlist->groups[i], args[1])) {
4234 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
4235 file, linenum, args[1], userlist->name);
4236 err_code |= ERR_ALERT;
4237 goto out;
4238 }
4239
4240 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
4241 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
4242 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
4245 }
4246
4247 cur_arg = 2;
4248
4249 while (*args[cur_arg]) {
4250 if (!strcmp(args[cur_arg], "users")) {
4251 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
4252 cur_arg += 2;
4253 continue;
4254 } else {
4255 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
4256 file, linenum, args[0]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260 }
4261
4262 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
4263 } else if (!strcmp(args[0], "user")) { /* new user */
4264 struct auth_users *newuser;
4265 int cur_arg;
4266
4267 if (!*args[1]) {
4268 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
4269 file, linenum, args[0]);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273
4274 for (newuser = userlist->users; newuser; newuser = newuser->next)
4275 if (!strcmp(newuser->user, args[1])) {
4276 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
4277 file, linenum, args[1], userlist->name);
4278 err_code |= ERR_ALERT;
4279 goto out;
4280 }
4281
4282 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
4283 if (!newuser) {
4284 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4285 err_code |= ERR_ALERT | ERR_ABORT;
4286 goto out;
4287 }
4288
4289 newuser->user = strdup(args[1]);
4290
4291 newuser->next = userlist->users;
4292 userlist->users = newuser;
4293
4294 cur_arg = 2;
4295
4296 while (*args[cur_arg]) {
4297 if (!strcmp(args[cur_arg], "password")) {
4298#ifndef CONFIG_HAP_CRYPT
4299 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
4300 file, linenum);
4301 err_code |= ERR_ALERT;
4302#endif
4303 newuser->pass = strdup(args[cur_arg + 1]);
4304 cur_arg += 2;
4305 continue;
4306 } else if (!strcmp(args[cur_arg], "insecure-password")) {
4307 newuser->pass = strdup(args[cur_arg + 1]);
4308 newuser->flags |= AU_O_INSECURE;
4309 cur_arg += 2;
4310 continue;
4311 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01004312 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004313 cur_arg += 2;
4314 continue;
4315 } else {
4316 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
4317 file, linenum, args[0]);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321 }
4322 } else {
4323 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 }
4326
4327out:
4328 return err_code;
4329}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330
4331/*
4332 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004333 * Returns the error code, 0 if OK, or any combination of :
4334 * - ERR_ABORT: must abort ASAP
4335 * - ERR_FATAL: we can continue parsing but not start the service
4336 * - ERR_WARN: a warning has been emitted
4337 * - ERR_ALERT: an alert has been emitted
4338 * Only the two first ones can stop processing, the two others are just
4339 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004341int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004343 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 FILE *f;
4345 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004347 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 if ((f=fopen(file,"r")) == NULL)
4350 return -1;
4351
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004352 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004353 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004354 char *end;
4355 char *args[MAX_LINE_ARGS + 1];
4356 char *line = thisline;
4357
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 linenum++;
4359
4360 end = line + strlen(line);
4361
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004362 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4363 /* Check if we reached the limit and the last char is not \n.
4364 * Watch out for the last line without the terminating '\n'!
4365 */
4366 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004367 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004369 }
4370
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004372 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 line++;
4374
4375 arg = 0;
4376 args[arg] = line;
4377
4378 while (*line && arg < MAX_LINE_ARGS) {
4379 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4380 * C equivalent value. Other combinations left unchanged (eg: \1).
4381 */
4382 if (*line == '\\') {
4383 int skip = 0;
4384 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4385 *line = line[1];
4386 skip = 1;
4387 }
4388 else if (line[1] == 'r') {
4389 *line = '\r';
4390 skip = 1;
4391 }
4392 else if (line[1] == 'n') {
4393 *line = '\n';
4394 skip = 1;
4395 }
4396 else if (line[1] == 't') {
4397 *line = '\t';
4398 skip = 1;
4399 }
4400 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004401 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 unsigned char hex1, hex2;
4403 hex1 = toupper(line[2]) - '0';
4404 hex2 = toupper(line[3]) - '0';
4405 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4406 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4407 *line = (hex1<<4) + hex2;
4408 skip = 3;
4409 }
4410 else {
4411 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 }
4414 }
4415 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004416 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004417 end -= skip;
4418 }
4419 line++;
4420 }
4421 else if (*line == '#' || *line == '\n' || *line == '\r') {
4422 /* end of string, end of loop */
4423 *line = 0;
4424 break;
4425 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004426 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004428 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004429 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004430 line++;
4431 args[++arg] = line;
4432 }
4433 else {
4434 line++;
4435 }
4436 }
4437
4438 /* empty line */
4439 if (!**args)
4440 continue;
4441
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004442 if (*line) {
4443 /* we had to stop due to too many args.
4444 * Let's terminate the string, print the offending part then cut the
4445 * last arg.
4446 */
4447 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4448 line++;
4449 *line = '\0';
4450
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004451 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004452 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 args[arg] = line;
4455 }
4456
Willy Tarreau540abe42007-05-02 20:50:16 +02004457 /* zero out remaining args and ensure that at least one entry
4458 * is zeroed out.
4459 */
4460 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 args[arg] = line;
4462 }
4463
Willy Tarreau3842f002009-06-14 11:39:52 +02004464 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004465 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004466 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004467 for (arg=0; *args[arg+1]; arg++)
4468 args[arg] = args[arg+1]; // shift args after inversion
4469 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004470 else if (!strcmp(args[0], "default")) {
4471 kwm = KWM_DEF;
4472 for (arg=0; *args[arg+1]; arg++)
4473 args[arg] = args[arg+1]; // shift args after inversion
4474 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004475
Willy Tarreau3842f002009-06-14 11:39:52 +02004476 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4477 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004478 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004479 }
4480
Willy Tarreau977b8e42006-12-29 14:19:17 +01004481 if (!strcmp(args[0], "listen") ||
4482 !strcmp(args[0], "frontend") ||
4483 !strcmp(args[0], "backend") ||
4484 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004485 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004487 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004488 cursection = strdup(args[0]);
4489 }
4490 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004492 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004493 cursection = strdup(args[0]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004494 } else if (!strcmp(args[0], "userlist")) {
4495 confsect = CFG_USERLIST;
4496 free(cursection);
4497 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 /* else it's a section keyword */
4500
4501 switch (confsect) {
4502 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 break;
4505 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004506 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004508 case CFG_USERLIST:
4509 err_code |= cfg_parse_users(file, linenum, args, kwm);
4510 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004512 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004513 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004515
4516 if (err_code & ERR_ABORT)
4517 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004519 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004520 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004522 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004523}
4524
Willy Tarreaubb925012009-07-23 13:36:36 +02004525/*
4526 * Returns the error code, 0 if OK, or any combination of :
4527 * - ERR_ABORT: must abort ASAP
4528 * - ERR_FATAL: we can continue parsing but not start the service
4529 * - ERR_WARN: a warning has been emitted
4530 * - ERR_ALERT: an alert has been emitted
4531 * Only the two first ones can stop processing, the two others are just
4532 * indicators.
4533 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004534int check_config_validity()
4535{
4536 int cfgerr = 0;
4537 struct proxy *curproxy = NULL;
4538 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01004539 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004540 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004541 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542
4543 /*
4544 * Now, check for the integrity of all that we have collected.
4545 */
4546
4547 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004548 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004550 /* first, we will invert the proxy list order */
4551 curproxy = NULL;
4552 while (proxy) {
4553 struct proxy *next;
4554
4555 next = proxy->next;
4556 proxy->next = curproxy;
4557 curproxy = proxy;
4558 if (!next)
4559 break;
4560 proxy = next;
4561 }
4562
Willy Tarreaubaaee002006-06-26 02:48:02 +02004563 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004564 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 }
4568
4569 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004570 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004571 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004572 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004573 unsigned int next_id;
4574
4575 if (!curproxy->uuid) {
4576 /* proxy ID not set, use automatic numbering with first
4577 * spare entry starting with next_pxid.
4578 */
4579 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4580 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4581 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004582 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01004583 next_pxid++;
4584
Willy Tarreau55ea7572007-06-17 19:56:27 +02004585
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004587 /* ensure we don't keep listeners uselessly bound */
4588 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 curproxy = curproxy->next;
4590 continue;
4591 }
4592
Willy Tarreauff01a212009-03-15 13:46:16 +01004593 switch (curproxy->mode) {
4594 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004595 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004596 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004597 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004599 cfgerr++;
4600 }
4601
4602 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004603 Warning("config : servers will be ignored for %s '%s'.\n",
4604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004605 break;
4606
4607 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004608 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004609 break;
4610
4611 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004612 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004613 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004614 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4615 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004616 cfgerr++;
4617 }
4618 break;
4619 }
4620
4621 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004622 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 cfgerr++;
4625 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004626
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004627 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004628 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004629 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004630 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4631 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004632 cfgerr++;
4633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004635 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004636 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4637 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004638 cfgerr++;
4639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004641 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004642 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4643 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004644 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004645 }
4646 }
4647 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4648 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4649 /* If no LB algo is set in a backend, and we're not in
4650 * transparent mode, dispatch mode nor proxy mode, we
4651 * want to use balance roundrobin by default.
4652 */
4653 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4654 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
4656 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004657
Willy Tarreau82936582007-11-30 15:20:09 +01004658 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4659 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004660 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4661 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004662 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004663 }
4664
Willy Tarreauef781042010-01-27 11:53:01 +01004665 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4666 curproxy->options &= ~PR_O2_CHK_SNDST;
4667 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4668 "send-state", proxy_type_str(curproxy), curproxy->id);
4669 err_code |= ERR_WARN;
4670 }
4671
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004672 /* if a default backend was specified, let's find it */
4673 if (curproxy->defbe.name) {
4674 struct proxy *target;
4675
Alex Williams96532db2009-11-01 21:27:13 -05004676 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004677 if (!target) {
4678 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4679 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004680 cfgerr++;
4681 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004682 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4683 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004684 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004685 } else {
4686 free(curproxy->defbe.name);
4687 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004688 /* we force the backend to be present on at least all of
4689 * the frontend's processes.
4690 */
4691 target->bind_proc = curproxy->bind_proc ?
4692 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 }
4694 }
4695
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004696 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004697 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4698 /* map jump target for ACT_SETBE in req_rep chain */
4699 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004700 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004701 struct proxy *target;
4702
Willy Tarreaua496b602006-12-17 23:15:24 +01004703 if (exp->action != ACT_SETBE)
4704 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004705
Alex Williams96532db2009-11-01 21:27:13 -05004706 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004707 if (!target) {
4708 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4709 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004710 cfgerr++;
4711 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004712 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4713 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004714 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004715 } else {
4716 free((void *)exp->replace);
4717 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004718 /* we force the backend to be present on at least all of
4719 * the frontend's processes.
4720 */
4721 target->bind_proc = curproxy->bind_proc ?
4722 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004723 }
4724 }
4725 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004726
4727 /* find the target proxy for 'use_backend' rules */
4728 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004729 struct proxy *target;
4730
Alex Williams96532db2009-11-01 21:27:13 -05004731 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004732
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004733 if (!target) {
4734 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4735 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004736 cfgerr++;
4737 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004738 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4739 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004740 cfgerr++;
4741 } else {
4742 free((void *)rule->be.name);
4743 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004744 /* we force the backend to be present on at least all of
4745 * the frontend's processes.
4746 */
4747 target->bind_proc = curproxy->bind_proc ?
4748 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004749 }
4750 }
4751
Emeric Brunb982a3d2010-01-04 15:45:53 +01004752 /* find the target table for 'stick' rules */
4753 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4754 struct proxy *target;
4755
Emeric Brun1d33b292010-01-04 15:47:17 +01004756 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4757 if (mrule->flags & STK_IS_STORE)
4758 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4759
Emeric Brunb982a3d2010-01-04 15:45:53 +01004760 if (mrule->table.name)
4761 target = findproxy(mrule->table.name, PR_CAP_BE);
4762 else
4763 target = curproxy;
4764
4765 if (!target) {
4766 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4767 curproxy->id, mrule->table.name);
4768 cfgerr++;
4769 }
4770 else if (target->table.size == 0) {
4771 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4772 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4773 cfgerr++;
4774 }
4775 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4776 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4777 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4778 cfgerr++;
4779 }
4780 else {
4781 free((void *)mrule->table.name);
4782 mrule->table.t = &(target->table);
4783 }
4784 }
4785
4786 /* find the target table for 'store response' rules */
4787 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4788 struct proxy *target;
4789
Emeric Brun1d33b292010-01-04 15:47:17 +01004790 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4791
Emeric Brunb982a3d2010-01-04 15:45:53 +01004792 if (mrule->table.name)
4793 target = findproxy(mrule->table.name, PR_CAP_BE);
4794 else
4795 target = curproxy;
4796
4797 if (!target) {
4798 Alert("Proxy '%s': unable to find store table '%s'.\n",
4799 curproxy->id, mrule->table.name);
4800 cfgerr++;
4801 }
4802 else if (target->table.size == 0) {
4803 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4804 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4805 cfgerr++;
4806 }
4807 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4808 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4809 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4810 cfgerr++;
4811 }
4812 else {
4813 free((void *)mrule->table.name);
4814 mrule->table.t = &(target->table);
4815 }
4816 }
4817
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004818 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
4819 !LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004820 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
4821 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
4822 "proxy", curproxy->id);
4823 cfgerr++;
4824 goto out_uri_auth_compat;
4825 }
4826
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004827 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004828 const char *uri_auth_compat_req[10];
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004829 struct req_acl_rule *req_acl;
Willy Tarreau95fa4692010-02-01 13:05:50 +01004830 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004831
Willy Tarreau95fa4692010-02-01 13:05:50 +01004832 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
4833 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004834
4835 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01004836 uri_auth_compat_req[i++] = "realm";
4837 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
4838 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004839
Willy Tarreau95fa4692010-02-01 13:05:50 +01004840 uri_auth_compat_req[i++] = "unless";
4841 uri_auth_compat_req[i++] = "{";
4842 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
4843 uri_auth_compat_req[i++] = "}";
4844 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004845
Willy Tarreau95fa4692010-02-01 13:05:50 +01004846 req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
4847 if (!req_acl) {
4848 cfgerr++;
4849 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004850 }
4851
Willy Tarreau95fa4692010-02-01 13:05:50 +01004852 LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
4853
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004854 if (curproxy->uri_auth->auth_realm) {
4855 free(curproxy->uri_auth->auth_realm);
4856 curproxy->uri_auth->auth_realm = NULL;
4857 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01004858
4859 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004860 }
4861out_uri_auth_compat:
4862
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01004863 cfgerr += acl_find_targets(curproxy);
4864
Willy Tarreau2738a142006-07-08 17:28:09 +02004865 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004866 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004867 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004868 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004869 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004870 " | While not properly invalid, you will certainly encounter various problems\n"
4871 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004872 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004873 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004874 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004875 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004876
Willy Tarreau1fa31262007-12-03 00:36:16 +01004877 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4878 * We must still support older configurations, so let's find out whether those
4879 * parameters have been set or must be copied from contimeouts.
4880 */
4881 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004882 if (!curproxy->timeout.tarpit ||
4883 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004884 /* tarpit timeout not set. We search in the following order:
4885 * default.tarpit, curr.connect, default.connect.
4886 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004887 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004888 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004889 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004890 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004891 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004892 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004893 }
4894 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004895 (!curproxy->timeout.queue ||
4896 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004897 /* queue timeout not set. We search in the following order:
4898 * default.queue, curr.connect, default.connect.
4899 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004900 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004901 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004902 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004903 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004904 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004905 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004906 }
4907 }
4908
Willy Tarreauf3c69202006-07-09 16:42:34 +02004909 if (curproxy->options & PR_O_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01004910 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
4911 curproxy->check_req = (char *)malloc(curproxy->check_len);
4912 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02004913 }
4914
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004915 /* The small pools required for the capture lists */
4916 if (curproxy->nb_req_cap)
4917 curproxy->req_cap_pool = create_pool("ptrcap",
4918 curproxy->nb_req_cap * sizeof(char *),
4919 MEM_F_SHARED);
4920 if (curproxy->nb_rsp_cap)
4921 curproxy->rsp_cap_pool = create_pool("ptrcap",
4922 curproxy->nb_rsp_cap * sizeof(char *),
4923 MEM_F_SHARED);
4924
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004925 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4926 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4927 MEM_F_SHARED);
4928
Willy Tarreau86034312006-12-29 00:10:33 +01004929 /* for backwards compatibility with "listen" instances, if
4930 * fullconn is not set but maxconn is set, then maxconn
4931 * is used.
4932 */
4933 if (!curproxy->fullconn)
4934 curproxy->fullconn = curproxy->maxconn;
4935
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 /* first, we will invert the servers list order */
4937 newsrv = NULL;
4938 while (curproxy->srv) {
4939 struct server *next;
4940
4941 next = curproxy->srv->next;
4942 curproxy->srv->next = newsrv;
4943 newsrv = curproxy->srv;
4944 if (!next)
4945 break;
4946 curproxy->srv = next;
4947 }
4948
Willy Tarreau20697042007-11-15 23:26:18 +01004949 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004950 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004952 /* We have to initialize the server lookup mechanism depending
4953 * on what LB algorithm was choosen.
4954 */
4955
4956 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4957 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4958 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004959 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4960 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4961 init_server_map(curproxy);
4962 } else {
4963 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4964 fwrr_init_server_groups(curproxy);
4965 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004966 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004967
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004968 case BE_LB_KIND_LC:
4969 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004970 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004971 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004972
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004973 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004974 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4975 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4976 chash_init_server_tree(curproxy);
4977 } else {
4978 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4979 init_server_map(curproxy);
4980 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004981 break;
4982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983
4984 if (curproxy->options & PR_O_LOGASAP)
4985 curproxy->to_log &= ~LW_BYTES;
4986
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004987 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4988 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4989 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4990 proxy_type_str(curproxy), curproxy->id);
4991 err_code |= ERR_WARN;
4992 }
4993
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004995 * ensure that we're not cross-dressing a TCP server into HTTP.
4996 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004997 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004998 newsrv = curproxy->srv;
4999 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005000 if (!newsrv->puid) {
5001 /* server ID not set, use automatic numbering with first
5002 * spare entry starting with next_svid.
5003 */
5004 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5005 newsrv->conf.id.key = newsrv->puid = next_id;
5006 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005007 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005008 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005009
Willy Tarreau21d2af32008-02-14 20:25:24 +01005010 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005011 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
5012 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005013 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01005014 }
5015 newsrv = newsrv->next;
5016 }
5017
5018 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 * If this server supports a maxconn parameter, it needs a dedicated
5020 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005021 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 */
5023 newsrv = curproxy->srv;
5024 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01005025 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 /* Only 'minconn' was specified, or it was higher than or equal
5027 * to 'maxconn'. Let's turn this into maxconn and clean it, as
5028 * this will avoid further useless expensive computations.
5029 */
5030 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01005031 } else if (newsrv->maxconn && !newsrv->minconn) {
5032 /* minconn was not specified, so we set it to maxconn */
5033 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005034 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005035 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
5036 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005037 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 }
5039
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005040 if (newsrv->trackit) {
5041 struct proxy *px;
5042 struct server *srv;
5043 char *pname, *sname;
5044
5045 pname = newsrv->trackit;
5046 sname = strrchr(pname, '/');
5047
5048 if (sname)
5049 *sname++ = '\0';
5050 else {
5051 sname = pname;
5052 pname = NULL;
5053 }
5054
5055 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005056 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005057 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005058 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5059 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005060 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005061 cfgerr++;
5062 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005063 }
5064 } else
5065 px = curproxy;
5066
5067 srv = findserver(px, sname);
5068 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005069 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5070 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005071 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005072 cfgerr++;
5073 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005074 }
5075
5076 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005077 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005078 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005079 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005080 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005081 cfgerr++;
5082 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005083 }
5084
5085 if (curproxy != px &&
5086 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005087 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01005088 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005089 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005090 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005091 cfgerr++;
5092 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005093 }
5094
5095 newsrv->tracked = srv;
5096 newsrv->tracknext = srv->tracknext;
5097 srv->tracknext = newsrv;
5098
5099 free(newsrv->trackit);
5100 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005101 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 newsrv = newsrv->next;
5103 }
5104
Willy Tarreauc1a21672009-08-16 22:37:44 +02005105 if (curproxy->cap & PR_CAP_FE) {
5106 if (curproxy->tcp_req.inspect_delay ||
5107 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5108 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5109
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005110 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005111 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005112 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005113 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005114
5115 /* both TCP and HTTP must check switching rules */
5116 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5117 }
5118
5119 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005120 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005121 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005122 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005123 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005124
Emeric Brunb982a3d2010-01-04 15:45:53 +01005125 /* init table on backend capabilities proxy */
5126 stktable_init(&curproxy->table);
5127
Willy Tarreauc1a21672009-08-16 22:37:44 +02005128 /* If the backend does requires RDP cookie persistence, we have to
5129 * enable the corresponding analyser.
5130 */
5131 if (curproxy->options2 & PR_O2_RDPC_PRST)
5132 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5133 }
5134
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005135 listener = NULL;
5136 while (curproxy->listen) {
5137 struct listener *next;
5138
5139 next = curproxy->listen->next;
5140 curproxy->listen->next = listener;
5141 listener = curproxy->listen;
5142
5143 if (!next)
5144 break;
5145
5146 curproxy->listen = next;
5147 }
5148
Willy Tarreaue6b98942007-10-29 01:09:36 +01005149 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005150 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005151 listener = curproxy->listen;
5152 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005153 if (!listener->luid) {
5154 /* listener ID not set, use automatic numbering with first
5155 * spare entry starting with next_luid.
5156 */
5157 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5158 listener->conf.id.key = listener->luid = next_id;
5159 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005160 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005161 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005162
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005163 /* enable separate counters */
5164 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5165 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5166 if (!listener->name) {
5167 sprintf(trash, "sock-%d", listener->luid);
5168 listener->name = strdup(trash);
5169 }
5170 }
5171
Willy Tarreaue6b98942007-10-29 01:09:36 +01005172 if (curproxy->options & PR_O_TCP_NOLING)
5173 listener->options |= LI_O_NOLINGER;
5174 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005175 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005176 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005177 listener->accept = event_accept;
5178 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005179 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005180 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005181
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005182 /* smart accept mode is automatic in HTTP mode */
5183 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5184 (curproxy->mode == PR_MODE_HTTP &&
5185 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5186 listener->options |= LI_O_NOQUICKACK;
5187
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005188 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005189 listener = listener->next;
5190 }
5191
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 curproxy = curproxy->next;
5193 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005194
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005195 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
5196 struct auth_users *curuser;
5197 int g;
5198
5199 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5200 unsigned int group_mask = 0;
5201 char *group = NULL;
5202
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005203 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005204 continue;
5205
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005206 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005207
5208 for (g = 0; g < curuserlist->grpcnt; g++)
5209 if (!strcmp(curuserlist->groups[g], group))
5210 break;
5211
5212 if (g == curuserlist->grpcnt) {
5213 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
5214 curuserlist->name, group, curuser->user);
5215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
5217 }
5218
5219 group_mask |= (1 << g);
5220 }
5221
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005222 free(curuser->u.groups);
5223 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005224 }
5225
5226 for (g = 0; g < curuserlist->grpcnt; g++) {
5227 char *user = NULL;
5228
5229 if (!curuserlist->groupusers[g])
5230 continue;
5231
5232 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
5233 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
5234 if (!strcmp(curuser->user, user))
5235 break;
5236
5237 if (!curuser) {
5238 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
5239 curuserlist->name, user, curuserlist->groups[g]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005244 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005245 }
5246
5247 free(curuserlist->groupusers[g]);
5248 }
5249
5250 free(curuserlist->groupusers);
5251
5252#ifdef DEBUG_AUTH
5253 for (g = 0; g < curuserlist->grpcnt; g++) {
5254 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
5255
5256 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
5257 if (curuser->group_mask & (1 << g))
5258 fprintf(stderr, " %s", curuser->user);
5259 }
5260
5261 fprintf(stderr, "\n");
5262 }
5263#endif
5264
5265 }
5266
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005267 /*
5268 * Recount currently required checks.
5269 */
5270
5271 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5272 int optnum;
5273
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005274 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5275 if (curproxy->options & cfg_opts[optnum].val)
5276 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005277
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005278 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5279 if (curproxy->options2 & cfg_opts2[optnum].val)
5280 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005281 }
5282
Willy Tarreaubb925012009-07-23 13:36:36 +02005283 if (cfgerr > 0)
5284 err_code |= ERR_ALERT | ERR_FATAL;
5285 out:
5286 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287}
5288
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005289/*
5290 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5291 * parsing sessions.
5292 */
5293void cfg_register_keywords(struct cfg_kw_list *kwl)
5294{
5295 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5296}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005298/*
5299 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5300 */
5301void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5302{
5303 LIST_DEL(&kwl->list);
5304 LIST_INIT(&kwl->list);
5305}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306
5307/*
5308 * Local variables:
5309 * c-indent-level: 8
5310 * c-basic-offset: 8
5311 * End:
5312 */