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