blob: 77e61d864d2032292b1edfea7529537e8c6655f2 [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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010050#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020051#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010052#include <proto/protocols.h>
53#include <proto/proto_tcp.h>
54#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010055#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010057#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010059#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060
61
Willy Tarreauf3c69202006-07-09 16:42:34 +020062/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
63 * ssl-hello-chk option to ensure that the remote server speaks SSL.
64 *
65 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
66 */
67const char sslv3_client_hello_pkt[] = {
68 "\x16" /* ContentType : 0x16 = Hanshake */
69 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
70 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
71 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
72 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
73 "\x03\x00" /* Hello Version : 0x0300 = v3 */
74 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
75 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
76 "\x00" /* Session ID length : empty (no session ID) */
77 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
78 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
79 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
80 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
81 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
82 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
83 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
84 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
85 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
86 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
87 "\x00\x38" "\x00\x39" "\x00\x3A"
88 "\x01" /* Compression Length : 0x01 = 1 byte for types */
89 "\x00" /* Compression Type : 0x00 = NULL compression */
90};
91
Willy Tarreau3842f002009-06-14 11:39:52 +020092/* various keyword modifiers */
93enum kw_mod {
94 KWM_STD = 0, /* normal */
95 KWM_NO, /* "no" prefixed before the keyword */
96 KWM_DEF, /* "default" prefixed before the keyword */
97};
98
Willy Tarreau13943ab2006-12-31 00:24:10 +010099/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100100struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101 const char *name;
102 unsigned int val;
103 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100104 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105};
106
107/* proxy->options */
108static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100111 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100112 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100114 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
115 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100116 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100117 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
118 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100120 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100121 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
122 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100123 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100124 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
125 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100126#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100127 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100128#endif
129
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100130 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100131};
132
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100133/* proxy->options2 */
134static const struct cfg_opt cfg_opts2[] =
135{
136#ifdef CONFIG_HAP_LINUX_SPLICE
137 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
138 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
140#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200141 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
142 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200143 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
144 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200145 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200146 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200147 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200148 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200149 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau88d349d2010-01-25 12:15:43 +0100150 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151 { NULL, 0, 0, 0 }
152};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153
Willy Tarreau6daf3432008-01-22 16:44:08 +0100154static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
156int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100157int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200158
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200159/* List head of all known configuration keywords */
160static struct cfg_kw_list cfg_keywords = {
161 .list = LIST_HEAD_INIT(cfg_keywords.list)
162};
163
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164/*
165 * converts <str> to a list of listeners which are dynamically allocated.
166 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
167 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
168 * - <port> is a numerical port from 1 to 65535 ;
169 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
170 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200171 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200173static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174{
175 struct listener *l;
176 char *c, *next, *range, *dupstr;
177 int port, end;
178
179 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200180
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181 while (next && *next) {
182 struct sockaddr_storage ss;
183
184 str = next;
185 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100186 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 *next++ = 0;
188 }
189
190 /* 2) look for the addr/port delimiter, it's the last colon. */
191 if ((range = strrchr(str, ':')) == NULL) {
192 Alert("Missing port number: '%s'\n", str);
193 goto fail;
194 }
195
196 *range++ = 0;
197
198 if (strrchr(str, ':') != NULL) {
199 /* IPv6 address contains ':' */
200 memset(&ss, 0, sizeof(ss));
201 ss.ss_family = AF_INET6;
202
203 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
204 Alert("Invalid server address: '%s'\n", str);
205 goto fail;
206 }
207 }
208 else {
209 memset(&ss, 0, sizeof(ss));
210 ss.ss_family = AF_INET;
211
212 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
213 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
214 }
215 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
216 struct hostent *he;
217
218 if ((he = gethostbyname(str)) == NULL) {
219 Alert("Invalid server name: '%s'\n", str);
220 goto fail;
221 }
222 else
223 ((struct sockaddr_in *)&ss)->sin_addr =
224 *(struct in_addr *) *(he->h_addr_list);
225 }
226 }
227
228 /* 3) look for the port-end delimiter */
229 if ((c = strchr(range, '-')) != NULL) {
230 *c++ = 0;
231 end = atol(c);
232 }
233 else {
234 end = atol(range);
235 }
236
237 port = atol(range);
238
239 if (port < 1 || port > 65535) {
240 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
241 goto fail;
242 }
243
244 if (end < 1 || end > 65535) {
245 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
246 goto fail;
247 }
248
249 for (; port <= end; port++) {
250 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200251 l->next = curproxy->listen;
252 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
254 l->fd = -1;
255 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100256 l->state = LI_INIT;
257
258 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100260 tcpv6_add_listener(l);
261 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100263 tcpv4_add_listener(l);
264 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200265
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 } /* end for(port) */
268 } /* end while(next) */
269 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200270 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 fail:
272 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200273 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274}
275
Willy Tarreau977b8e42006-12-29 14:19:17 +0100276/*
277 * Sends a warning if proxy <proxy> does not have at least one of the
278 * capabilities in <cap>. An optionnal <hint> may be added at the end
279 * of the warning to help the user. Returns 1 if a warning was emitted
280 * or 0 if the condition is valid.
281 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100282int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100283{
284 char *msg;
285
286 switch (cap) {
287 case PR_CAP_BE: msg = "no backend"; break;
288 case PR_CAP_FE: msg = "no frontend"; break;
289 case PR_CAP_RS: msg = "no ruleset"; break;
290 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
291 default: msg = "not enough"; break;
292 }
293
294 if (!(proxy->cap & cap)) {
295 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100296 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100297 return 1;
298 }
299 return 0;
300}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301
Willy Tarreau61d18892009-03-31 10:49:21 +0200302/* Report a warning if a rule is placed after a 'block' rule.
303 * Return 1 if the warning has been emitted, otherwise 0.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200306{
307 if (!LIST_ISEMPTY(&proxy->block_cond)) {
308 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
309 file, line, arg);
310 return 1;
311 }
312 return 0;
313}
314
315/* Report a warning if a rule is placed after a reqrewrite rule.
316 * Return 1 if the warning has been emitted, otherwise 0.
317 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100318int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200319{
320 if (proxy->req_exp) {
321 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
322 file, line, arg);
323 return 1;
324 }
325 return 0;
326}
327
328/* Report a warning if a rule is placed after a reqadd rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100333 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a redirect rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a 'use_backend' rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
359 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100368int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200369{
370 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
371 warnif_rule_after_reqadd(proxy, file, line, arg) ||
372 warnif_rule_after_redirect(proxy, file, line, arg) ||
373 warnif_rule_after_use_backend(proxy, file, line, arg);
374}
375
376/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
379 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
380 warnif_rule_after_redirect(proxy, file, line, arg) ||
381 warnif_rule_after_use_backend(proxy, file, line, arg);
382}
383
384/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100391/* Report it if a request ACL condition uses some response-only parameters. It
392 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
393 * Note that <cond> may be NULL and then will be ignored.
394 */
395static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
396{
397 struct acl *acl;
398
399 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
400 return 0;
401
402 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
403 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
404 file, line, acl ? acl->name : "(unknown)");
405 return ERR_WARN;
406}
407
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100408/* Report it if a request ACL condition uses some request-only volatile parameters.
409 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
410 * Note that <cond> may be NULL and then will be ignored.
411 */
412static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
413{
414 struct acl *acl;
415
416 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
417 return 0;
418
419 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
420 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
421 file, line, acl ? acl->name : "(unknown)");
422 return ERR_WARN;
423}
424
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200427 * parse a line in a <global> section. Returns the error code, 0 if OK, or
428 * any combination of :
429 * - ERR_ABORT: must abort ASAP
430 * - ERR_FATAL: we can continue parsing but not start the service
431 * - ERR_WARN: a warning has been emitted
432 * - ERR_ALERT: an alert has been emitted
433 * Only the two first ones can stop processing, the two others are just
434 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200435 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200436int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200437{
Willy Tarreau058e9072009-07-20 09:30:05 +0200438 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200439
440 if (!strcmp(args[0], "global")) { /* new section */
441 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443 }
444 else if (!strcmp(args[0], "daemon")) {
445 global.mode |= MODE_DAEMON;
446 }
447 else if (!strcmp(args[0], "debug")) {
448 global.mode |= MODE_DEBUG;
449 }
450 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100451 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200453 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100454 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200455 }
456 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100457 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100460 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100462 else if (!strcmp(args[0], "nosplice")) {
463 global.tune.options &= ~GTUNE_USE_SPLICE;
464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465 else if (!strcmp(args[0], "quiet")) {
466 global.mode |= MODE_QUIET;
467 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200468 else if (!strcmp(args[0], "tune.maxpollevents")) {
469 if (global.tune.maxpollevents != 0) {
470 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 err_code |= ERR_ALERT;
472 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200473 }
474 if (*(args[1]) == 0) {
475 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200476 err_code |= ERR_ALERT | ERR_FATAL;
477 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200478 }
479 global.tune.maxpollevents = atol(args[1]);
480 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100481 else if (!strcmp(args[0], "tune.maxaccept")) {
482 if (global.tune.maxaccept != 0) {
483 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200484 err_code |= ERR_ALERT;
485 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100486 }
487 if (*(args[1]) == 0) {
488 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT | ERR_FATAL;
490 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100491 }
492 global.tune.maxaccept = atol(args[1]);
493 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200494 else if (!strcmp(args[0], "tune.bufsize")) {
495 if (*(args[1]) == 0) {
496 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
497 err_code |= ERR_ALERT | ERR_FATAL;
498 goto out;
499 }
500 global.tune.bufsize = atol(args[1]);
501 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
502 global.tune.maxrewrite = global.tune.bufsize / 2;
503 }
504 else if (!strcmp(args[0], "tune.maxrewrite")) {
505 if (*(args[1]) == 0) {
506 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
507 err_code |= ERR_ALERT | ERR_FATAL;
508 goto out;
509 }
510 global.tune.maxrewrite = atol(args[1]);
511 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
512 global.tune.maxrewrite = global.tune.bufsize / 2;
513 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100514 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
515 if (global.tune.client_rcvbuf != 0) {
516 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
517 err_code |= ERR_ALERT;
518 goto out;
519 }
520 if (*(args[1]) == 0) {
521 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
522 err_code |= ERR_ALERT | ERR_FATAL;
523 goto out;
524 }
525 global.tune.client_rcvbuf = atol(args[1]);
526 }
527 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
528 if (global.tune.server_rcvbuf != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT;
531 goto out;
532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
537 }
538 global.tune.server_rcvbuf = atol(args[1]);
539 }
540 else if (!strcmp(args[0], "tune.sndbuf.client")) {
541 if (global.tune.client_sndbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.client_sndbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.sndbuf.server")) {
554 if (global.tune.server_sndbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.server_sndbuf = atol(args[1]);
565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 else if (!strcmp(args[0], "uid")) {
567 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200568 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200569 err_code |= ERR_ALERT;
570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 }
577 global.uid = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "gid")) {
580 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200581 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 err_code |= ERR_ALERT;
583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
590 global.gid = atol(args[1]);
591 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 /* user/group name handling */
593 else if (!strcmp(args[0], "user")) {
594 struct passwd *ha_user;
595 if (global.uid != 0) {
596 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 err_code |= ERR_ALERT;
598 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200599 }
600 errno = 0;
601 ha_user = getpwnam(args[1]);
602 if (ha_user != NULL) {
603 global.uid = (int)ha_user->pw_uid;
604 }
605 else {
606 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 +0200607 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200608 }
609 }
610 else if (!strcmp(args[0], "group")) {
611 struct group *ha_group;
612 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200613 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 }
617 errno = 0;
618 ha_group = getgrnam(args[1]);
619 if (ha_group != NULL) {
620 global.gid = (int)ha_group->gr_gid;
621 }
622 else {
623 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 +0200624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200625 }
626 }
627 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 else if (!strcmp(args[0], "nbproc")) {
629 if (global.nbproc != 0) {
630 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT;
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 }
634 if (*(args[1]) == 0) {
635 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 }
639 global.nbproc = atol(args[1]);
640 }
641 else if (!strcmp(args[0], "maxconn")) {
642 if (global.maxconn != 0) {
643 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200644 err_code |= ERR_ALERT;
645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 }
652 global.maxconn = atol(args[1]);
653#ifdef SYSTEM_MAXCONN
654 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
655 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);
656 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 }
659#endif /* SYSTEM_MAXCONN */
660 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100661 else if (!strcmp(args[0], "maxpipes")) {
662 if (global.maxpipes != 0) {
663 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200664 err_code |= ERR_ALERT;
665 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100666 }
667 if (*(args[1]) == 0) {
668 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200669 err_code |= ERR_ALERT | ERR_FATAL;
670 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100671 }
672 global.maxpipes = atol(args[1]);
673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 else if (!strcmp(args[0], "ulimit-n")) {
675 if (global.rlimit_nofile != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685 global.rlimit_nofile = atol(args[1]);
686 }
687 else if (!strcmp(args[0], "chroot")) {
688 if (global.chroot != NULL) {
689 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 if (*(args[1]) == 0) {
694 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 }
698 global.chroot = strdup(args[1]);
699 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200700 else if (!strcmp(args[0], "description")) {
701 int i, len=0;
702 char *d;
703
704 if (!*args[1]) {
705 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
706 file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710
711 for(i=1; *args[i]; i++)
712 len += strlen(args[i])+1;
713
714 if (global.desc)
715 free(global.desc);
716
717 global.desc = d = (char *)calloc(1, len);
718
719 d += sprintf(d, "%s", args[1]);
720 for(i=2; *args[i]; i++)
721 d += sprintf(d, " %s", args[i]);
722 }
723 else if (!strcmp(args[0], "node")) {
724 int i;
725 char c;
726
727 for (i=0; args[1][i]; i++) {
728 c = args[1][i];
729 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
730 break;
731 }
732
733 if (!i || args[1][i]) {
734 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
735 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
736 file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740
741 if (global.node)
742 free(global.node);
743
744 global.node = strdup(args[1]);
745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 else if (!strcmp(args[0], "pidfile")) {
747 if (global.pidfile != NULL) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 }
757 global.pidfile = strdup(args[1]);
758 }
759 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100760 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200761 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762
763 if (*(args[1]) == 0 || *(args[2]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
768
769 facility = get_log_facility(args[2]);
770 if (facility < 0) {
771 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200772 err_code |= ERR_ALERT | ERR_FATAL;
773 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200774 }
775
776 level = 7; /* max syslog level = debug */
777 if (*(args[3])) {
778 level = get_log_level(args[3]);
779 if (level < 0) {
780 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
782 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 }
784 }
785
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200786 minlvl = 0; /* limit syslog level to this level (emerg) */
787 if (*(args[4])) {
788 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200789 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200790 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT | ERR_FATAL;
792 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200793 }
794 }
795
Robert Tsai81ae1952007-12-05 10:47:29 +0100796 if (args[1][0] == '/') {
797 logsrv.u.addr.sa_family = AF_UNIX;
798 logsrv.u.un = *str2sun(args[1]);
799 } else {
800 logsrv.u.addr.sa_family = AF_INET;
801 logsrv.u.in = *str2sa(args[1]);
802 if (!logsrv.u.in.sin_port)
803 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
804 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805
806 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100807 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808 global.logfac1 = facility;
809 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200810 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100813 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 global.logfac2 = facility;
815 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200816 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 else {
819 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200822 }
823 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
824 if (global.spread_checks != 0) {
825 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT;
827 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200833 }
834 global.spread_checks = atol(args[1]);
835 if (global.spread_checks < 0 || global.spread_checks > 50) {
836 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200841 struct cfg_kw_list *kwl;
842 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200843 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200844
845 list_for_each_entry(kwl, &cfg_keywords.list, list) {
846 for (index = 0; kwl->kw[index].kw != NULL; index++) {
847 if (kwl->kw[index].section != CFG_GLOBAL)
848 continue;
849 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
850 /* prepare error message just in case */
851 snprintf(trash, sizeof(trash),
852 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200853 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
854 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200855 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200856 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200857 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200858 else if (rc > 0) {
859 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_WARN;
861 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200862 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200863 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200864 }
865 }
866 }
867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200869 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200871
Willy Tarreau058e9072009-07-20 09:30:05 +0200872 out:
873 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874}
875
Willy Tarreau97cb7802010-01-03 20:23:58 +0100876/* Perform the most basic initialization of a proxy :
877 * memset(), list_init(*), reset_timeouts(*).
878 */
879static void init_new_proxy(struct proxy *p)
880{
881 memset(p, 0, sizeof(struct proxy));
882 LIST_INIT(&p->pendconns);
883 LIST_INIT(&p->acl);
884 LIST_INIT(&p->block_cond);
885 LIST_INIT(&p->redirect_rules);
886 LIST_INIT(&p->mon_fail_cond);
887 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100888 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100889 LIST_INIT(&p->sticking_rules);
890 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100891 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100892 LIST_INIT(&p->req_add);
893 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100894
895 /* Timeouts are defined as -1 */
896 proxy_reset_timeouts(p);
897}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200899void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100901 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 defproxy.mode = PR_MODE_TCP;
903 defproxy.state = PR_STNEW;
904 defproxy.maxconn = cfg_maxpconn;
905 defproxy.conn_retries = CONN_RETRIES;
906 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100907
908 defproxy.defsrv.inter = DEF_CHKINTR;
909 defproxy.defsrv.fastinter = 0;
910 defproxy.defsrv.downinter = 0;
911 defproxy.defsrv.rise = DEF_RISETIME;
912 defproxy.defsrv.fall = DEF_FALLTIME;
913 defproxy.defsrv.check_port = 0;
914 defproxy.defsrv.maxqueue = 0;
915 defproxy.defsrv.minconn = 0;
916 defproxy.defsrv.maxconn = 0;
917 defproxy.defsrv.slowstart = 0;
918 defproxy.defsrv.onerror = DEF_HANA_ONERR;
919 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
920 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921}
922
Willy Tarreauade5ec42010-01-28 19:33:49 +0100923
924static int create_cond_regex_rule(const char *file, int line,
925 struct proxy *px, int dir, int action, int flags,
926 const char *cmd, const char *reg, const char *repl,
927 const char **cond_start)
928{
929 regex_t *preg = NULL;
930 const char *err;
931 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +0100932 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +0100933
934 if (px == &defproxy) {
935 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto err;
938 }
939
940 if (*reg == 0) {
941 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto err;
944 }
945
946 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
947 err_code |= ERR_WARN;
948
Willy Tarreau5321c422010-01-28 20:35:13 +0100949 if (cond_start &&
950 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
951 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
952 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
953 file, line, cmd);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto err;
956 }
957 }
958 else if (cond_start && **cond_start) {
959 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
960 file, line, cmd, *cond_start);
961 err_code |= ERR_ALERT | ERR_FATAL;
962 goto err;
963 }
964
965 if (dir == ACL_DIR_REQ)
966 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100967 else
968 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +0100969
Willy Tarreauade5ec42010-01-28 19:33:49 +0100970 preg = calloc(1, sizeof(regex_t));
971 if (!preg) {
972 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
973 err_code = ERR_ALERT | ERR_FATAL;
974 goto err;
975 }
976
977 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
978 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
979 err_code = ERR_ALERT | ERR_FATAL;
980 goto err;
981 }
982
983 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +0100984 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +0100985 if (repl && err) {
986 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
987 file, line, cmd, *err);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto err;
990 }
991
992 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
993 err_code |= ERR_WARN;
994
995 return err_code;
996 err:
997 free(preg);
998 return err_code;
999}
1000
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001002 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001003 * Returns the error code, 0 if OK, or any combination of :
1004 * - ERR_ABORT: must abort ASAP
1005 * - ERR_FATAL: we can continue parsing but not start the service
1006 * - ERR_WARN: a warning has been emitted
1007 * - ERR_ALERT: an alert has been emitted
1008 * Only the two first ones can stop processing, the two others are just
1009 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010 */
Willy Tarreau3842f002009-06-14 11:39:52 +02001011int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001012{
1013 static struct proxy *curproxy = NULL;
1014 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001015 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001016 int rc;
1017 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001018 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001019 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020
Willy Tarreau977b8e42006-12-29 14:19:17 +01001021 if (!strcmp(args[0], "listen"))
1022 rc = PR_CAP_LISTEN;
1023 else if (!strcmp(args[0], "frontend"))
1024 rc = PR_CAP_FE | PR_CAP_RS;
1025 else if (!strcmp(args[0], "backend"))
1026 rc = PR_CAP_BE | PR_CAP_RS;
1027 else if (!strcmp(args[0], "ruleset"))
1028 rc = PR_CAP_RS;
1029 else
1030 rc = PR_CAP_NONE;
1031
1032 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 if (!*args[1]) {
1034 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1035 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001037 err_code |= ERR_ALERT | ERR_ABORT;
1038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001040
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001041 err = invalid_char(args[1]);
1042 if (err) {
1043 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1044 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001045 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001046 }
1047
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001048 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1049 /*
1050 * If there are two proxies with the same name only following
1051 * combinations are allowed:
1052 *
1053 * listen backend frontend ruleset
1054 * listen - - - -
1055 * backend - - OK -
1056 * frontend - OK - -
1057 * ruleset - - - -
1058 */
1059
1060 if (!strcmp(curproxy->id, args[1]) &&
1061 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1062 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001063 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1064 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1065 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001066 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001067 }
1068 }
1069
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001072 err_code |= ERR_ALERT | ERR_ABORT;
1073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001075
Willy Tarreau97cb7802010-01-03 20:23:58 +01001076 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 curproxy->next = proxy;
1078 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001079 curproxy->conf.file = file;
1080 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001081 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001083 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084
1085 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001086 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001087 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001088 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001089 err_code |= ERR_FATAL;
1090 goto out;
1091 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001092 new = curproxy->listen;
1093 while (new != last) {
1094 new->conf.file = file;
1095 new->conf.line = linenum;
1096 new = new->next;
1097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 global.maxsock++;
1099 }
1100
1101 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001102 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
1103
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001105 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001106 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001107 curproxy->no_options = defproxy.no_options;
1108 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001109 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001110 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001111 curproxy->except_net = defproxy.except_net;
1112 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001113 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001114 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001116 if (defproxy.fwdfor_hdr_len) {
1117 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1118 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1119 }
1120
Willy Tarreaub86db342009-11-30 11:50:16 +01001121 if (defproxy.orgto_hdr_len) {
1122 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1123 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1124 }
1125
Willy Tarreau977b8e42006-12-29 14:19:17 +01001126 if (curproxy->cap & PR_CAP_FE) {
1127 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001128 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001129 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001130
1131 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001132 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1133 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001134
1135 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137
Willy Tarreau977b8e42006-12-29 14:19:17 +01001138 if (curproxy->cap & PR_CAP_BE) {
1139 curproxy->fullconn = defproxy.fullconn;
1140 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141
Willy Tarreau977b8e42006-12-29 14:19:17 +01001142 if (defproxy.check_req)
1143 curproxy->check_req = strdup(defproxy.check_req);
1144 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146 if (defproxy.cookie_name)
1147 curproxy->cookie_name = strdup(defproxy.cookie_name);
1148 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001149 if (defproxy.cookie_domain)
1150 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001151
Emeric Brun647caf12009-06-30 17:57:00 +02001152 if (defproxy.rdp_cookie_name)
1153 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1154 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1155
Willy Tarreau01732802007-11-01 22:48:15 +01001156 if (defproxy.url_param_name)
1157 curproxy->url_param_name = strdup(defproxy.url_param_name);
1158 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001159
Benoitaffb4812009-03-25 13:02:10 +01001160 if (defproxy.hh_name)
1161 curproxy->hh_name = strdup(defproxy.hh_name);
1162 curproxy->hh_len = defproxy.hh_len;
1163 curproxy->hh_match_domain = defproxy.hh_match_domain;
1164
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001165 if (defproxy.iface_name)
1166 curproxy->iface_name = strdup(defproxy.iface_name);
1167 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001170 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001171 if (defproxy.capture_name)
1172 curproxy->capture_name = strdup(defproxy.capture_name);
1173 curproxy->capture_namelen = defproxy.capture_namelen;
1174 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001176
Willy Tarreau977b8e42006-12-29 14:19:17 +01001177 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001178 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001179 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001180 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001181 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001182 curproxy->uri_auth = defproxy.uri_auth;
1183 curproxy->mon_net = defproxy.mon_net;
1184 curproxy->mon_mask = defproxy.mon_mask;
1185 if (defproxy.monitor_uri)
1186 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1187 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001188 if (defproxy.defbe.name)
1189 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001190 }
1191
1192 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001193 curproxy->timeout.connect = defproxy.timeout.connect;
1194 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001195 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001196 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001197 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001198 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001199 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001200 curproxy->source_addr = defproxy.source_addr;
1201 }
1202
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 curproxy->mode = defproxy.mode;
1204 curproxy->logfac1 = defproxy.logfac1;
1205 curproxy->logsrv1 = defproxy.logsrv1;
1206 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001207 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 curproxy->logfac2 = defproxy.logfac2;
1209 curproxy->logsrv2 = defproxy.logsrv2;
1210 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001211 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001213 curproxy->conf.used_listener_id = EB_ROOT;
1214 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001215
Willy Tarreau93893792009-07-23 13:19:11 +02001216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1219 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001220 /* FIXME-20070101: we should do this too at the end of the
1221 * config parsing to free all default values.
1222 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001223 free(defproxy.check_req);
1224 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001225 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001226 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001227 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001228 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001229 free(defproxy.capture_name);
1230 free(defproxy.monitor_uri);
1231 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001232 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001233 free(defproxy.fwdfor_hdr_name);
1234 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001235 free(defproxy.orgto_hdr_name);
1236 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001237
Willy Tarreaua534fea2008-08-03 12:19:50 +02001238 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001239 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001240
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 /* we cannot free uri_auth because it might already be used */
1242 init_default_instance();
1243 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001244 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 }
1247 else if (curproxy == NULL) {
1248 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001251 }
1252
Willy Tarreau977b8e42006-12-29 14:19:17 +01001253
1254 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001256 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001257 int cur_arg;
1258
Willy Tarreaubaaee002006-06-26 02:48:02 +02001259 if (curproxy == &defproxy) {
1260 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001264 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001265 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001266
1267 if (strchr(args[1], ':') == NULL) {
1268 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001272 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001273
1274 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001275 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001276 err_code |= ERR_ALERT | ERR_FATAL;
1277 goto out;
1278 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001279
Willy Tarreau90a570f2009-10-04 20:54:54 +02001280 new_listen = curproxy->listen;
1281 while (new_listen != last_listen) {
1282 new_listen->conf.file = file;
1283 new_listen->conf.line = linenum;
1284 new_listen = new_listen->next;
1285 }
1286
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001287 cur_arg = 2;
1288 while (*(args[cur_arg])) {
1289 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1290#ifdef SO_BINDTODEVICE
1291 struct listener *l;
1292
1293 if (!*args[cur_arg + 1]) {
1294 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1295 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001298 }
1299
1300 for (l = curproxy->listen; l != last_listen; l = l->next)
1301 l->interface = strdup(args[cur_arg + 1]);
1302
1303 global.last_checks |= LSTCHK_NETADM;
1304
1305 cur_arg += 2;
1306 continue;
1307#else
1308 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1309 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001312#endif
1313 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001314 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1315#ifdef TCP_MAXSEG
1316 struct listener *l;
1317 int mss;
1318
1319 if (!*args[cur_arg + 1]) {
1320 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1321 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001324 }
1325
1326 mss = str2uic(args[cur_arg + 1]);
1327 if (mss < 1 || mss > 65535) {
1328 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001332 }
1333
1334 for (l = curproxy->listen; l != last_listen; l = l->next)
1335 l->maxseg = mss;
1336
1337 cur_arg += 2;
1338 continue;
1339#else
1340 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1341 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001344#endif
1345 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001346
1347 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1348#ifdef TCP_DEFER_ACCEPT
1349 struct listener *l;
1350
1351 for (l = curproxy->listen; l != last_listen; l = l->next)
1352 l->options |= LI_O_DEF_ACCEPT;
1353
1354 cur_arg ++;
1355 continue;
1356#else
1357 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1358 file, linenum, args[0], args[cur_arg]);
1359 err_code |= ERR_ALERT | ERR_FATAL;
1360 goto out;
1361#endif
1362 }
1363
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001364 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001365#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001366 struct listener *l;
1367
1368 for (l = curproxy->listen; l != last_listen; l = l->next)
1369 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001370
1371 cur_arg ++;
1372 continue;
1373#else
1374 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1375 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001378#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001379 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001380
1381 if (!strcmp(args[cur_arg], "name")) {
1382 struct listener *l;
1383
1384 for (l = curproxy->listen; l != last_listen; l = l->next)
1385 l->name = strdup(args[cur_arg + 1]);
1386
1387 cur_arg += 2;
1388 continue;
1389 }
1390
1391 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001392 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001393 struct listener *l;
1394
1395 if (curproxy->listen->next != last_listen) {
1396 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1397 file, linenum, args[cur_arg]);
1398 err_code |= ERR_ALERT | ERR_FATAL;
1399 goto out;
1400 }
1401
1402 if (!*args[cur_arg + 1]) {
1403 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1404 file, linenum, args[cur_arg]);
1405 err_code |= ERR_ALERT | ERR_FATAL;
1406 goto out;
1407 }
1408
1409 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001410 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001411
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001412 if (curproxy->listen->luid <= 0) {
1413 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001414 file, linenum);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001419 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1420 if (node) {
1421 l = container_of(node, struct listener, conf.id);
1422 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1423 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1424 err_code |= ERR_ALERT | ERR_FATAL;
1425 goto out;
1426 }
1427 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1428
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001429 cur_arg += 2;
1430 continue;
1431 }
1432
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001433 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 +01001434 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 }
1441 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1442 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1443 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001449 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 /* flush useless bits */
1452 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001455 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001457 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458
Willy Tarreau1c47f852006-07-09 08:22:27 +02001459 if (!*args[1]) {
1460 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001464 }
1465
Willy Tarreaua534fea2008-08-03 12:19:50 +02001466 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001467 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001468 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001469 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001470 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1471
Willy Tarreau93893792009-07-23 13:19:11 +02001472 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1475 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1476 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1477 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1478 else {
1479 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 }
1483 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001484 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001485 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001486
1487 if (curproxy == &defproxy) {
1488 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001492 }
1493
1494 if (!*args[1]) {
1495 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1496 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001499 }
1500
1501 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001502 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001503
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001504 if (curproxy->uuid <= 0) {
1505 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001506 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001509 }
1510
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001511 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1512 if (node) {
1513 struct proxy *target = container_of(node, struct proxy, conf.id);
1514 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1515 file, linenum, proxy_type_str(curproxy), curproxy->id,
1516 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001521 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001522 else if (!strcmp(args[0], "description")) {
1523 int i, len=0;
1524 char *d;
1525
Cyril Bonté99ed3272010-01-24 23:29:44 +01001526 if (curproxy == &defproxy) {
1527 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1528 file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001533 if (!*args[1]) {
1534 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1535 file, linenum, args[0]);
1536 return -1;
1537 }
1538
1539 for(i=1; *args[i]; i++)
1540 len += strlen(args[i])+1;
1541
1542 d = (char *)calloc(1, len);
1543 curproxy->desc = d;
1544
1545 d += sprintf(d, "%s", args[1]);
1546 for(i=2; *args[i]; i++)
1547 d += sprintf(d, " %s", args[i]);
1548
1549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1551 curproxy->state = PR_STSTOPPED;
1552 }
1553 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1554 curproxy->state = PR_STNEW;
1555 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001556 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1557 int cur_arg = 1;
1558 unsigned int set = 0;
1559
1560 while (*args[cur_arg]) {
1561 int u;
1562 if (strcmp(args[cur_arg], "all") == 0) {
1563 set = 0;
1564 break;
1565 }
1566 else if (strcmp(args[cur_arg], "odd") == 0) {
1567 set |= 0x55555555;
1568 }
1569 else if (strcmp(args[cur_arg], "even") == 0) {
1570 set |= 0xAAAAAAAA;
1571 }
1572 else {
1573 u = str2uic(args[cur_arg]);
1574 if (u < 1 || u > 32) {
1575 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001579 }
1580 if (u > global.nbproc) {
1581 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001584 }
1585 set |= 1 << (u - 1);
1586 }
1587 cur_arg++;
1588 }
1589 curproxy->bind_proc = set;
1590 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001591 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001592 if (curproxy == &defproxy) {
1593 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001596 }
1597
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001598 err = invalid_char(args[1]);
1599 if (err) {
1600 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1601 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001602 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001603 }
1604
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001605 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1606 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1607 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
1609 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001610 }
1611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1613 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614
Willy Tarreau977b8e42006-12-29 14:19:17 +01001615 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 if (*(args[1]) == 0) {
1619 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001624
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001625 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 curproxy->cookie_name = strdup(args[1]);
1628 curproxy->cookie_len = strlen(curproxy->cookie_name);
1629
1630 cur_arg = 2;
1631 while (*(args[cur_arg])) {
1632 if (!strcmp(args[cur_arg], "rewrite")) {
1633 curproxy->options |= PR_O_COOK_RW;
1634 }
1635 else if (!strcmp(args[cur_arg], "indirect")) {
1636 curproxy->options |= PR_O_COOK_IND;
1637 }
1638 else if (!strcmp(args[cur_arg], "insert")) {
1639 curproxy->options |= PR_O_COOK_INS;
1640 }
1641 else if (!strcmp(args[cur_arg], "nocache")) {
1642 curproxy->options |= PR_O_COOK_NOC;
1643 }
1644 else if (!strcmp(args[cur_arg], "postonly")) {
1645 curproxy->options |= PR_O_COOK_POST;
1646 }
1647 else if (!strcmp(args[cur_arg], "prefix")) {
1648 curproxy->options |= PR_O_COOK_PFX;
1649 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001650 else if (!strcmp(args[cur_arg], "domain")) {
1651 if (!*args[cur_arg + 1]) {
1652 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1653 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001656 }
1657
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001658 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001659 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001660 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1661 " dots nor does not start with a dot."
1662 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001663 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001664 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001665 }
1666
1667 err = invalid_domainchar(args[cur_arg + 1]);
1668 if (err) {
1669 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1670 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001673 }
1674
Willy Tarreau68a897b2009-12-03 23:28:34 +01001675 if (!curproxy->cookie_domain) {
1676 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1677 } else {
1678 /* one domain was already specified, add another one by
1679 * building the string which will be returned along with
1680 * the cookie.
1681 */
1682 char *new_ptr;
1683 int new_len = strlen(curproxy->cookie_domain) +
1684 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1685 new_ptr = malloc(new_len);
1686 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1687 free(curproxy->cookie_domain);
1688 curproxy->cookie_domain = new_ptr;
1689 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001690 cur_arg++;
1691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001693 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 }
1698 cur_arg++;
1699 }
1700 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1701 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1702 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001703 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 }
1705
1706 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1707 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1708 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001709 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 }
1711 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001712 else if (!strcmp(args[0], "persist")) { /* persist */
1713 if (*(args[1]) == 0) {
1714 Alert("parsing [%s:%d] : missing persist method.\n",
1715 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001718 }
1719
1720 if (!strncmp(args[1], "rdp-cookie", 10)) {
1721 curproxy->options2 |= PR_O2_RDPC_PRST;
1722
Emeric Brunb982a3d2010-01-04 15:45:53 +01001723 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001724 const char *beg, *end;
1725
1726 beg = args[1] + 11;
1727 end = strchr(beg, ')');
1728
1729 if (!end || end == beg) {
1730 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\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 free(curproxy->rdp_cookie_name);
1737 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1738 curproxy->rdp_cookie_len = end-beg;
1739 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001740 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001741 free(curproxy->rdp_cookie_name);
1742 curproxy->rdp_cookie_name = strdup("msts");
1743 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1744 }
1745 else { /* syntax */
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 else {
1753 Alert("parsing [%s:%d] : unknown persist method.\n",
1754 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001757 }
1758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001760 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001762 if (curproxy == &defproxy) {
1763 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
Willy Tarreau977b8e42006-12-29 14:19:17 +01001768 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001772 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 }
1777 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001778 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 curproxy->appsession_name = strdup(args[1]);
1780 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1781 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001782 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1783 if (err) {
1784 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1785 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001788 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001789 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001790
Willy Tarreau51041c72007-09-09 21:56:53 +02001791 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1792 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001793 err_code |= ERR_ALERT | ERR_ABORT;
1794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001796
1797 cur_arg = 6;
1798 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001799 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1800 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001801 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001802 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001803 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001804 } else if (!strcmp(args[cur_arg], "prefix")) {
1805 curproxy->options2 |= PR_O2_AS_PFX;
1806 } else if (!strcmp(args[cur_arg], "mode")) {
1807 if (!*args[cur_arg + 1]) {
1808 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1809 file, linenum, args[0], args[cur_arg]);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813
1814 cur_arg++;
1815 if (!strcmp(args[cur_arg], "query-string")) {
1816 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1817 curproxy->options2 |= PR_O2_AS_M_QS;
1818 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1819 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1820 curproxy->options2 |= PR_O2_AS_M_PP;
1821 } else {
1822 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825 }
1826 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001827 cur_arg++;
1828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829 } /* Url App Session */
1830 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001831 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001832 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833
Willy Tarreaubaaee002006-06-26 02:48:02 +02001834 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001835 if (curproxy == &defproxy) {
1836 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841 if (*(args[4]) == 0) {
1842 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001847 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 curproxy->capture_name = strdup(args[2]);
1849 curproxy->capture_namelen = strlen(curproxy->capture_name);
1850 curproxy->capture_len = atol(args[4]);
1851 if (curproxy->capture_len >= CAPTURE_LEN) {
1852 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1853 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001854 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 curproxy->capture_len = CAPTURE_LEN - 1;
1856 }
1857 curproxy->to_log |= LW_COOKIE;
1858 }
1859 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1860 struct cap_hdr *hdr;
1861
1862 if (curproxy == &defproxy) {
1863 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 +02001864 err_code |= ERR_ALERT | ERR_FATAL;
1865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867
1868 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1869 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1870 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 }
1874
1875 hdr = calloc(sizeof(struct cap_hdr), 1);
1876 hdr->next = curproxy->req_cap;
1877 hdr->name = strdup(args[3]);
1878 hdr->namelen = strlen(args[3]);
1879 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001880 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 hdr->index = curproxy->nb_req_cap++;
1882 curproxy->req_cap = hdr;
1883 curproxy->to_log |= LW_REQHDR;
1884 }
1885 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1886 struct cap_hdr *hdr;
1887
1888 if (curproxy == &defproxy) {
1889 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 +02001890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 }
1893
1894 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1895 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1896 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 }
1900 hdr = calloc(sizeof(struct cap_hdr), 1);
1901 hdr->next = curproxy->rsp_cap;
1902 hdr->name = strdup(args[3]);
1903 hdr->namelen = strlen(args[3]);
1904 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001905 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 hdr->index = curproxy->nb_rsp_cap++;
1907 curproxy->rsp_cap = hdr;
1908 curproxy->to_log |= LW_RSPHDR;
1909 }
1910 else {
1911 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1912 file, linenum, args[0]);
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 if (*(args[1]) == 0) {
1922 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_ALERT | ERR_FATAL;
1925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
1927 curproxy->conn_retries = atol(args[1]);
1928 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001929 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001930 if (curproxy == &defproxy) {
1931 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001934 }
1935
Willy Tarreauef6494c2010-01-28 17:12:36 +01001936 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001937 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001941 }
1942
Willy Tarreauef6494c2010-01-28 17:12:36 +01001943 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001944 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1945 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001948 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01001949
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001950 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001951 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001952 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001953 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001954 struct redirect_rule *rule;
1955 int cur_arg;
1956 int type = REDIRECT_TYPE_NONE;
1957 int code = 302;
1958 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001959 char *cookie = NULL;
1960 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001961 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001962
Cyril Bonté99ed3272010-01-24 23:29:44 +01001963 if (curproxy == &defproxy) {
1964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
1967 }
1968
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001969 cur_arg = 1;
1970 while (*(args[cur_arg])) {
1971 if (!strcmp(args[cur_arg], "location")) {
1972 if (!*args[cur_arg + 1]) {
1973 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1974 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001977 }
1978
1979 type = REDIRECT_TYPE_LOCATION;
1980 cur_arg++;
1981 destination = args[cur_arg];
1982 }
1983 else if (!strcmp(args[cur_arg], "prefix")) {
1984 if (!*args[cur_arg + 1]) {
1985 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1986 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001989 }
1990
1991 type = REDIRECT_TYPE_PREFIX;
1992 cur_arg++;
1993 destination = args[cur_arg];
1994 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001995 else if (!strcmp(args[cur_arg], "set-cookie")) {
1996 if (!*args[cur_arg + 1]) {
1997 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1998 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002001 }
2002
2003 cur_arg++;
2004 cookie = args[cur_arg];
2005 cookie_set = 1;
2006 }
2007 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2008 if (!*args[cur_arg + 1]) {
2009 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2010 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002013 }
2014
2015 cur_arg++;
2016 cookie = args[cur_arg];
2017 cookie_set = 0;
2018 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002019 else if (!strcmp(args[cur_arg],"code")) {
2020 if (!*args[cur_arg + 1]) {
2021 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002025 }
2026 cur_arg++;
2027 code = atol(args[cur_arg]);
2028 if (code < 301 || code > 303) {
2029 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2030 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002033 }
2034 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002035 else if (!strcmp(args[cur_arg],"drop-query")) {
2036 flags |= REDIRECT_FLAG_DROP_QS;
2037 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002038 else if (!strcmp(args[cur_arg],"append-slash")) {
2039 flags |= REDIRECT_FLAG_APPEND_SLASH;
2040 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002041 else if (strcmp(args[cur_arg], "if") == 0 ||
2042 strcmp(args[cur_arg], "unless") == 0) {
2043 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2044 if (!cond) {
2045 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2046 file, linenum, args[0]);
2047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
2049 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002050 break;
2051 }
2052 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002053 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 +02002054 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002057 }
2058 cur_arg++;
2059 }
2060
2061 if (type == REDIRECT_TYPE_NONE) {
2062 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002066 }
2067
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002068 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2069 rule->cond = cond;
2070 rule->rdr_str = strdup(destination);
2071 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002072 if (cookie) {
2073 /* depending on cookie_set, either we want to set the cookie, or to clear it.
2074 * a clear consists in appending "; Max-Age=0" at the end.
2075 */
2076 rule->cookie_len = strlen(cookie);
2077 if (cookie_set)
2078 rule->cookie_str = strdup(cookie);
2079 else {
2080 rule->cookie_str = malloc(rule->cookie_len + 12);
2081 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2082 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
2083 rule->cookie_len += 11;
2084 }
2085 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002086 rule->type = type;
2087 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002088 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002089 LIST_INIT(&rule->list);
2090 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002091 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002092 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002093 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002094 struct switching_rule *rule;
2095
Willy Tarreaub099aca2008-10-12 17:26:37 +02002096 if (curproxy == &defproxy) {
2097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002100 }
2101
Willy Tarreau55ea7572007-06-17 19:56:27 +02002102 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002104
2105 if (*(args[1]) == 0) {
2106 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_ALERT | ERR_FATAL;
2108 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002109 }
2110
Willy Tarreauef6494c2010-01-28 17:12:36 +01002111 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002112 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2113 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002116 }
2117
Willy Tarreauef6494c2010-01-28 17:12:36 +01002118 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002119 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002120 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002123 }
2124
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002125 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002126
Willy Tarreau55ea7572007-06-17 19:56:27 +02002127 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2128 rule->cond = cond;
2129 rule->be.name = strdup(args[1]);
2130 LIST_INIT(&rule->list);
2131 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2132 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002133 else if (!strcmp(args[0], "force-persist")) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002134 struct force_persist_rule *rule;
2135
2136 if (curproxy == &defproxy) {
2137 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
2140 }
2141
2142 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2143 err_code |= ERR_WARN;
2144
Willy Tarreauef6494c2010-01-28 17:12:36 +01002145 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002146 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2147 file, linenum, args[0]);
2148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
2150 }
2151
Willy Tarreauef6494c2010-01-28 17:12:36 +01002152 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002153 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2154 file, linenum);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002159 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002160
2161 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2162 rule->cond = cond;
2163 LIST_INIT(&rule->list);
2164 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2165 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002166 else if (!strcmp(args[0], "stick-table")) {
2167 int myidx = 1;
2168
2169 curproxy->table.type = (unsigned int)-1;
2170 while (*args[myidx]) {
2171 const char *err;
2172
2173 if (strcmp(args[myidx], "size") == 0) {
2174 myidx++;
2175 if (!*(args[myidx])) {
2176 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2177 file, linenum, args[myidx-1]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2182 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2183 file, linenum, *err, args[myidx-1]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002187 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002188 }
2189 else if (strcmp(args[myidx], "expire") == 0) {
2190 myidx++;
2191 if (!*(args[myidx])) {
2192 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2193 file, linenum, args[myidx-1]);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
2196 }
2197 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2198 if (err) {
2199 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2200 file, linenum, *err, args[myidx-1]);
2201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
2203 }
2204 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002205 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002206 }
2207 else if (strcmp(args[myidx], "nopurge") == 0) {
2208 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002209 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002210 }
2211 else if (strcmp(args[myidx], "type") == 0) {
2212 myidx++;
2213 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2214 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2215 file, linenum, args[myidx]);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
2218 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002219 /* myidx already points to next arg */
2220 }
2221 else {
2222 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2223 file, linenum, args[myidx]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002226 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002227 }
2228
2229 if (!curproxy->table.size) {
2230 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2231 file, linenum);
2232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
2235
2236 if (curproxy->table.type == (unsigned int)-1) {
2237 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2238 file, linenum);
2239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
2241 }
2242 }
2243 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002244 struct sticking_rule *rule;
2245 struct pattern_expr *expr;
2246 int myidx = 0;
2247 const char *name = NULL;
2248 int flags;
2249
2250 if (curproxy == &defproxy) {
2251 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255
2256 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2257 err_code |= ERR_WARN;
2258 goto out;
2259 }
2260
2261 myidx++;
2262 if ((strcmp(args[myidx], "store") == 0) ||
2263 (strcmp(args[myidx], "store-request") == 0)) {
2264 myidx++;
2265 flags = STK_IS_STORE;
2266 }
2267 else if (strcmp(args[myidx], "store-response") == 0) {
2268 myidx++;
2269 flags = STK_IS_STORE | STK_ON_RSP;
2270 }
2271 else if (strcmp(args[myidx], "match") == 0) {
2272 myidx++;
2273 flags = STK_IS_MATCH;
2274 }
2275 else if (strcmp(args[myidx], "on") == 0) {
2276 myidx++;
2277 flags = STK_IS_MATCH | STK_IS_STORE;
2278 }
2279 else {
2280 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284
2285 if (*(args[myidx]) == 0) {
2286 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
2289 }
2290
2291 expr = pattern_parse_expr(args, &myidx);
2292 if (!expr) {
2293 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297
2298 if (flags & STK_ON_RSP) {
2299 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2300 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2301 file, linenum, args[0], expr->fetch->kw);
2302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
2305 } else {
2306 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2307 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2308 file, linenum, args[0], expr->fetch->kw);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312 }
2313
2314 if (strcmp(args[myidx], "table") == 0) {
2315 myidx++;
2316 name = args[myidx++];
2317 }
2318
Willy Tarreauef6494c2010-01-28 17:12:36 +01002319 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2320 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002321 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2322 file, linenum, args[0]);
2323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
2325 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002326 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002327 else if (*(args[myidx])) {
2328 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2329 file, linenum, args[0], args[myidx]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002334 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2335
Emeric Brunb982a3d2010-01-04 15:45:53 +01002336 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2337 rule->cond = cond;
2338 rule->expr = expr;
2339 rule->flags = flags;
2340 rule->table.name = name ? strdup(name) : NULL;
2341 LIST_INIT(&rule->list);
2342 if (flags & STK_ON_RSP)
2343 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2344 else
2345 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002348 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002350
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2352 curproxy->uri_auth = NULL; /* we must detach from the default config */
2353
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002354 if (!*args[1]) {
2355 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 } else if (!strcmp(args[1], "uri")) {
2357 if (*(args[2]) == 0) {
2358 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2362 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_ABORT;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
2366 } else if (!strcmp(args[1], "realm")) {
2367 if (*(args[2]) == 0) {
2368 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2372 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_ABORT;
2374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002376 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002377 unsigned interval;
2378
2379 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2380 if (err) {
2381 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2382 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002385 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_ABORT;
2388 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 } else if (!strcmp(args[1], "auth")) {
2391 if (*(args[2]) == 0) {
2392 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_ABORT;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400 } else if (!strcmp(args[1], "scope")) {
2401 if (*(args[2]) == 0) {
2402 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2406 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_ABORT;
2408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
2410 } else if (!strcmp(args[1], "enable")) {
2411 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_ABORT;
2414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002416 } else if (!strcmp(args[1], "hide-version")) {
2417 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2418 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002421 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002422 } else if (!strcmp(args[1], "show-legends")) {
2423 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2425 err_code |= ERR_ALERT | ERR_ABORT;
2426 goto out;
2427 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002428 } else if (!strcmp(args[1], "show-node")) {
2429
2430 if (*args[2]) {
2431 int i;
2432 char c;
2433
2434 for (i=0; args[2][i]; i++) {
2435 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002436 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002437 break;
2438 }
2439
2440 if (!i || args[2][i]) {
2441 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2442 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2443 file, linenum, args[0], args[1]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447 }
2448
2449 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2450 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2451 err_code |= ERR_ALERT | ERR_ABORT;
2452 goto out;
2453 }
2454 } else if (!strcmp(args[1], "show-desc")) {
2455 char *desc = NULL;
2456
2457 if (*args[2]) {
2458 int i, len=0;
2459 char *d;
2460
2461 for(i=2; *args[i]; i++)
2462 len += strlen(args[i])+1;
2463
2464 desc = d = (char *)calloc(1, len);
2465
2466 d += sprintf(d, "%s", args[2]);
2467 for(i=3; *args[i]; i++)
2468 d += sprintf(d, " %s", args[i]);
2469 }
2470
2471 if (!*args[2] && !global.desc)
2472 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2473 file, linenum, args[1]);
2474 else {
2475 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2476 free(desc);
2477 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2478 err_code |= ERR_ALERT | ERR_ABORT;
2479 goto out;
2480 }
2481 free(desc);
2482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002484stats_error_parsing:
2485 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2486 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490 }
2491 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002492 int optnum;
2493
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002494 if (*(args[1]) == '\0') {
2495 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2496 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002500
2501 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2502 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002503 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2504 err_code |= ERR_WARN;
2505 goto out;
2506 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002507
Willy Tarreau3842f002009-06-14 11:39:52 +02002508 curproxy->no_options &= ~cfg_opts[optnum].val;
2509 curproxy->options &= ~cfg_opts[optnum].val;
2510
2511 switch (kwm) {
2512 case KWM_STD:
2513 curproxy->options |= cfg_opts[optnum].val;
2514 break;
2515 case KWM_NO:
2516 curproxy->no_options |= cfg_opts[optnum].val;
2517 break;
2518 case KWM_DEF: /* already cleared */
2519 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002520 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002521
Willy Tarreau93893792009-07-23 13:19:11 +02002522 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002523 }
2524 }
2525
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002526 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2527 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002528 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2529 err_code |= ERR_WARN;
2530 goto out;
2531 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002532
Willy Tarreau3842f002009-06-14 11:39:52 +02002533 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2534 curproxy->options2 &= ~cfg_opts2[optnum].val;
2535
2536 switch (kwm) {
2537 case KWM_STD:
2538 curproxy->options2 |= cfg_opts2[optnum].val;
2539 break;
2540 case KWM_NO:
2541 curproxy->no_options2 |= cfg_opts2[optnum].val;
2542 break;
2543 case KWM_DEF: /* already cleared */
2544 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002545 }
Willy Tarreau93893792009-07-23 13:19:11 +02002546 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002547 }
2548 }
2549
Willy Tarreau3842f002009-06-14 11:39:52 +02002550 if (kwm != KWM_STD) {
2551 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002552 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002555 }
2556
Emeric Brun3a058f32009-06-30 18:26:00 +02002557 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002559 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002561 if (*(args[2]) != '\0') {
2562 if (!strcmp(args[2], "clf")) {
2563 curproxy->options2 |= PR_O2_CLFLOG;
2564 } else {
2565 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002568 }
2569 }
2570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 else if (!strcmp(args[1], "tcplog"))
2572 /* generate a detailed TCP log */
2573 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 else if (!strcmp(args[1], "tcpka")) {
2575 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002576 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002578
2579 if (curproxy->cap & PR_CAP_FE)
2580 curproxy->options |= PR_O_TCP_CLI_KA;
2581 if (curproxy->cap & PR_CAP_BE)
2582 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
2584 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002585 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_WARN;
2587
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002589 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002590 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002591 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002592 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002593 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 if (!*args[2]) { /* no argument */
2595 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2596 curproxy->check_len = strlen(DEF_CHECK_REQ);
2597 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002598 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 curproxy->check_req = (char *)malloc(reqlen);
2600 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002601 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01002603 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 if (*args[4])
2605 reqlen += strlen(args[4]);
2606 else
2607 reqlen += strlen("HTTP/1.0");
2608
2609 curproxy->check_req = (char *)malloc(reqlen);
2610 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01002611 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002613 }
2614 else if (!strcmp(args[1], "ssl-hello-chk")) {
2615 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002616 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002618
Willy Tarreaua534fea2008-08-03 12:19:50 +02002619 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002620 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002621 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002622 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002623 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
Willy Tarreau23677902007-05-08 23:50:35 +02002625 else if (!strcmp(args[1], "smtpchk")) {
2626 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002627 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002628 curproxy->options &= ~PR_O_HTTP_CHK;
2629 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002630 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002631 curproxy->options |= PR_O_SMTP_CHK;
2632
2633 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2634 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2635 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2636 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2637 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2638 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2639 curproxy->check_req = (char *)malloc(reqlen);
2640 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2641 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2642 } else {
2643 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2644 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2645 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2646 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2647 }
2648 }
2649 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002650 else if (!strcmp(args[1], "mysql-check")) {
2651 /* use MYSQL request to check servers' health */
2652 free(curproxy->check_req);
2653 curproxy->options &= ~PR_O_HTTP_CHK;
2654 curproxy->options &= ~PR_O_SSL3_CHK;
2655 curproxy->options &= ~PR_O_SMTP_CHK;
2656 curproxy->options2 |= PR_O2_MYSQL_CHK;
2657 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002658 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002659 int cur_arg;
2660
2661 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2662 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002663 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002664
2665 curproxy->options |= PR_O_FWDFOR;
2666
2667 free(curproxy->fwdfor_hdr_name);
2668 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2669 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2670
2671 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2672 cur_arg = 2;
2673 while (*(args[cur_arg])) {
2674 if (!strcmp(args[cur_arg], "except")) {
2675 /* suboption except - needs additional argument for it */
2676 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2677 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2678 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002681 }
2682 /* flush useless bits */
2683 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002684 cur_arg += 2;
2685 } else if (!strcmp(args[cur_arg], "header")) {
2686 /* suboption header - needs additional argument for it */
2687 if (*(args[cur_arg+1]) == 0) {
2688 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2689 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002692 }
2693 free(curproxy->fwdfor_hdr_name);
2694 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2695 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2696 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002697 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002698 /* unknown suboption - catchall */
2699 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2700 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002703 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002704 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002705 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002706 else if (!strcmp(args[1], "originalto")) {
2707 int cur_arg;
2708
2709 /* insert x-original-to field, but not for the IP address listed as an except.
2710 * set default options (ie: bitfield, header name, etc)
2711 */
2712
2713 curproxy->options |= PR_O_ORGTO;
2714
2715 free(curproxy->orgto_hdr_name);
2716 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2717 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2718
2719 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2720 cur_arg = 2;
2721 while (*(args[cur_arg])) {
2722 if (!strcmp(args[cur_arg], "except")) {
2723 /* suboption except - needs additional argument for it */
2724 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2725 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2726 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002729 }
2730 /* flush useless bits */
2731 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2732 cur_arg += 2;
2733 } else if (!strcmp(args[cur_arg], "header")) {
2734 /* suboption header - needs additional argument for it */
2735 if (*(args[cur_arg+1]) == 0) {
2736 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2737 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002740 }
2741 free(curproxy->orgto_hdr_name);
2742 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2743 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2744 cur_arg += 2;
2745 } else {
2746 /* unknown suboption - catchall */
2747 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2748 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002751 }
2752 } /* end while loop */
2753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 else {
2755 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 }
Willy Tarreau93893792009-07-23 13:19:11 +02002759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002761 else if (!strcmp(args[0], "default_backend")) {
2762 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002764
2765 if (*(args[1]) == 0) {
2766 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002769 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002770 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002771 curproxy->defbe.name = strdup(args[1]);
2772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002774 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002776
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002777 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 /* enable reconnections to dispatch */
2781 curproxy->options |= PR_O_REDISP;
2782 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002783 else if (!strcmp(args[0], "http-check")) {
2784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002786
2787 if (strcmp(args[1], "disable-on-404") == 0) {
2788 /* enable a graceful server shutdown on an HTTP 404 response */
2789 curproxy->options |= PR_O_DISABLE404;
2790 }
Willy Tarreauef781042010-01-27 11:53:01 +01002791 else if (strcmp(args[1], "send-state") == 0) {
2792 /* enable emission of the apparent state of a server in HTTP checks */
2793 curproxy->options2 |= PR_O2_CHK_SNDST;
2794 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002795 else {
2796 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002799 }
2800 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002801 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002802 if (curproxy == &defproxy) {
2803 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002806 }
2807
Willy Tarreaub80c2302007-11-30 20:51:32 +01002808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002810
2811 if (strcmp(args[1], "fail") == 0) {
2812 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01002813 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002814 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2815 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002818 }
2819
Willy Tarreauef6494c2010-01-28 17:12:36 +01002820 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01002821 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2822 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002825 }
2826 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2827 }
2828 else {
2829 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002832 }
2833 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834#ifdef TPROXY
2835 else if (!strcmp(args[0], "transparent")) {
2836 /* enable transparent proxy connections */
2837 curproxy->options |= PR_O_TRANSP;
2838 }
2839#endif
2840 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002841 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 if (*(args[1]) == 0) {
2845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 }
2849 curproxy->maxconn = atol(args[1]);
2850 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002851 else if (!strcmp(args[0], "backlog")) { /* backlog */
2852 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002854
2855 if (*(args[1]) == 0) {
2856 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002859 }
2860 curproxy->backlog = atol(args[1]);
2861 }
Willy Tarreau86034312006-12-29 00:10:33 +01002862 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865
Willy Tarreau86034312006-12-29 00:10:33 +01002866 if (*(args[1]) == 0) {
2867 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002870 }
2871 curproxy->fullconn = atol(args[1]);
2872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2874 if (*(args[1]) == 0) {
2875 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002879 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2880 if (err) {
2881 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2882 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002885 }
2886 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2889 if (curproxy == &defproxy) {
2890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002894 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 if (strchr(args[1], ':') == NULL) {
2898 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
2902 curproxy->dispatch_addr = *str2sa(args[1]);
2903 }
2904 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002907
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002908 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002909 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2910 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002915 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2916 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2917 err_code |= ERR_WARN;
2918
2919 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2920 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2921 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2922 }
2923 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2924 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2925 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2926 }
2927 else {
2928 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002933 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002935 char *rport, *raddr;
2936 short realport = 0;
2937 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002939 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002945 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946
2947 if (!*args[2]) {
2948 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002953
2954 err = invalid_char(args[1]);
2955 if (err) {
2956 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2957 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002960 }
2961
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2963 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_ABORT;
2965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002968 if (!defsrv) {
2969 /* the servers are linked backwards first */
2970 newsrv->next = curproxy->srv;
2971 curproxy->srv = newsrv;
2972 newsrv->proxy = curproxy;
2973 newsrv->conf.file = file;
2974 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002976 LIST_INIT(&newsrv->pendconns);
2977 do_check = 0;
2978 newsrv->state = SRV_RUNNING; /* early server setup */
2979 newsrv->last_change = now.tv_sec;
2980 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002982 /* several ways to check the port component :
2983 * - IP => port=+0, relative
2984 * - IP: => port=+0, relative
2985 * - IP:N => port=N, absolute
2986 * - IP:+N => port=+N, relative
2987 * - IP:-N => port=-N, relative
2988 */
2989 raddr = strdup(args[2]);
2990 rport = strchr(raddr, ':');
2991 if (rport) {
2992 *rport++ = 0;
2993 realport = atol(rport);
2994 if (!isdigit((unsigned char)*rport))
2995 newsrv->state |= SRV_MAPPORTS;
2996 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002998
2999 newsrv->addr = *str2sa(raddr);
3000 newsrv->addr.sin_port = htons(realport);
3001 free(raddr);
3002
3003 newsrv->check_port = curproxy->defsrv.check_port;
3004 newsrv->inter = curproxy->defsrv.inter;
3005 newsrv->fastinter = curproxy->defsrv.fastinter;
3006 newsrv->downinter = curproxy->defsrv.downinter;
3007 newsrv->rise = curproxy->defsrv.rise;
3008 newsrv->fall = curproxy->defsrv.fall;
3009 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3010 newsrv->minconn = curproxy->defsrv.minconn;
3011 newsrv->maxconn = curproxy->defsrv.maxconn;
3012 newsrv->slowstart = curproxy->defsrv.slowstart;
3013 newsrv->onerror = curproxy->defsrv.onerror;
3014 newsrv->consecutive_errors_limit
3015 = curproxy->defsrv.consecutive_errors_limit;
3016 newsrv->uweight = newsrv->iweight
3017 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003019 newsrv->curfd = -1; /* no health-check in progress */
3020 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003022 cur_arg = 3;
3023 } else {
3024 newsrv = &curproxy->defsrv;
3025 cur_arg = 1;
3026 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003027
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003029 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003030 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003031
3032 if (!*args[cur_arg + 1]) {
3033 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3034 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003037 }
3038
3039 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003040 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003042 if (newsrv->puid <= 0) {
3043 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003047 }
3048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003049 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3050 if (node) {
3051 struct server *target = container_of(node, struct server, conf.id);
3052 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3053 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003058 cur_arg += 2;
3059 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003060 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 newsrv->cookie = strdup(args[cur_arg + 1]);
3062 newsrv->cklen = strlen(args[cur_arg + 1]);
3063 cur_arg += 2;
3064 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003065 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003066 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3067 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3068 cur_arg += 2;
3069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003071 if (!*args[cur_arg + 1]) {
3072 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3073 file, linenum, args[cur_arg]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003079 if (newsrv->rise <= 0) {
3080 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3081 file, linenum, args[cur_arg]);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 newsrv->health = newsrv->rise;
3087 cur_arg += 2;
3088 }
3089 else if (!strcmp(args[cur_arg], "fall")) {
3090 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003091
3092 if (!*args[cur_arg + 1]) {
3093 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3094 file, linenum, args[cur_arg]);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098
3099 if (newsrv->fall <= 0) {
3100 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3101 file, linenum, args[cur_arg]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 cur_arg += 2;
3107 }
3108 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003109 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3110 if (err) {
3111 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3112 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003115 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003116 if (val <= 0) {
3117 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3118 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003121 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003122 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 cur_arg += 2;
3124 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003125 else if (!strcmp(args[cur_arg], "fastinter")) {
3126 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3127 if (err) {
3128 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3129 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003132 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003133 if (val <= 0) {
3134 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3135 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003138 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003139 newsrv->fastinter = val;
3140 cur_arg += 2;
3141 }
3142 else if (!strcmp(args[cur_arg], "downinter")) {
3143 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3144 if (err) {
3145 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3146 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003149 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003150 if (val <= 0) {
3151 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3152 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003155 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003156 newsrv->downinter = val;
3157 cur_arg += 2;
3158 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003159 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003160 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003161 cur_arg += 2;
3162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 else if (!strcmp(args[cur_arg], "port")) {
3164 newsrv->check_port = atol(args[cur_arg + 1]);
3165 cur_arg += 2;
3166 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003167 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 newsrv->state |= SRV_BACKUP;
3169 cur_arg ++;
3170 }
3171 else if (!strcmp(args[cur_arg], "weight")) {
3172 int w;
3173 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003174 if (w < 0 || w > 256) {
3175 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003180 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 cur_arg += 2;
3182 }
3183 else if (!strcmp(args[cur_arg], "minconn")) {
3184 newsrv->minconn = atol(args[cur_arg + 1]);
3185 cur_arg += 2;
3186 }
3187 else if (!strcmp(args[cur_arg], "maxconn")) {
3188 newsrv->maxconn = atol(args[cur_arg + 1]);
3189 cur_arg += 2;
3190 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003191 else if (!strcmp(args[cur_arg], "maxqueue")) {
3192 newsrv->maxqueue = atol(args[cur_arg + 1]);
3193 cur_arg += 2;
3194 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003195 else if (!strcmp(args[cur_arg], "slowstart")) {
3196 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003197 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003198 if (err) {
3199 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3200 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003203 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003204 if (val <= 0) {
3205 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3206 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003209 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003210 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003211 cur_arg += 2;
3212 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003213 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003214
3215 if (!*args[cur_arg + 1]) {
3216 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3217 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003220 }
3221
3222 newsrv->trackit = strdup(args[cur_arg + 1]);
3223
3224 cur_arg += 2;
3225 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003226 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 global.maxsock++;
3228 do_check = 1;
3229 cur_arg += 1;
3230 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003231 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003232 if (!strcmp(args[cur_arg + 1], "none"))
3233 newsrv->observe = HANA_OBS_NONE;
3234 else if (!strcmp(args[cur_arg + 1], "layer4"))
3235 newsrv->observe = HANA_OBS_LAYER4;
3236 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3237 if (curproxy->mode != PR_MODE_HTTP) {
3238 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3239 file, linenum, args[cur_arg + 1]);
3240 err_code |= ERR_ALERT;
3241 }
3242 newsrv->observe = HANA_OBS_LAYER7;
3243 }
3244 else {
3245 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3246 "'l4events', 'http-responses' but get '%s'\n",
3247 file, linenum, args[cur_arg], args[cur_arg + 1]);
3248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
3250 }
3251
3252 cur_arg += 2;
3253 }
3254 else if (!strcmp(args[cur_arg], "on-error")) {
3255 if (!strcmp(args[cur_arg + 1], "fastinter"))
3256 newsrv->onerror = HANA_ONERR_FASTINTER;
3257 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3258 newsrv->onerror = HANA_ONERR_FAILCHK;
3259 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3260 newsrv->onerror = HANA_ONERR_SUDDTH;
3261 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3262 newsrv->onerror = HANA_ONERR_MARKDWN;
3263 else {
3264 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3265 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3266 file, linenum, args[cur_arg], args[cur_arg + 1]);
3267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
3269 }
3270
3271 cur_arg += 2;
3272 }
3273 else if (!strcmp(args[cur_arg], "error-limit")) {
3274 if (!*args[cur_arg + 1]) {
3275 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3276 file, linenum, args[cur_arg]);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
3280
3281 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3282
3283 if (newsrv->consecutive_errors_limit <= 0) {
3284 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3285 file, linenum, args[cur_arg]);
3286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
3288 }
3289 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003290 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003291 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003293#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003294 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003295 file, linenum, "source", "usesrc");
3296#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003297 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003299#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
3303 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003304 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3305
3306 if (port_low != port_high) {
3307 int i;
3308 if (port_low <= 0 || port_low > 65535 ||
3309 port_high <= 0 || port_high > 65535 ||
3310 port_low > port_high) {
3311 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3312 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003315 }
3316 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3317 for (i = 0; i < newsrv->sport_range->size; i++)
3318 newsrv->sport_range->ports[i] = port_low + i;
3319 }
3320
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003322 while (*(args[cur_arg])) {
3323 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003324#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3325#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003326 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3327 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3328 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003331 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003332#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003333 if (!*args[cur_arg + 1]) {
3334 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3335 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003338 }
3339 if (!strcmp(args[cur_arg + 1], "client")) {
3340 newsrv->state |= SRV_TPROXY_CLI;
3341 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3342 newsrv->state |= SRV_TPROXY_CIP;
3343 } else {
3344 newsrv->state |= SRV_TPROXY_ADDR;
3345 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3346 }
3347 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003348#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003349 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003350#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003351 cur_arg += 2;
3352 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003353#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003354 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003355 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003358#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3359 } /* "usesrc" */
3360
3361 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3362#ifdef SO_BINDTODEVICE
3363 if (!*args[cur_arg + 1]) {
3364 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003368 }
3369 if (newsrv->iface_name)
3370 free(newsrv->iface_name);
3371
3372 newsrv->iface_name = strdup(args[cur_arg + 1]);
3373 newsrv->iface_len = strlen(newsrv->iface_name);
3374 global.last_checks |= LSTCHK_NETADM;
3375#else
3376 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3377 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003380#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003381 cur_arg += 2;
3382 continue;
3383 }
3384 /* this keyword in not an option of "source" */
3385 break;
3386 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003388 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003389 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3390 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003395 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003396 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 +01003397 file, linenum, newsrv->id);
3398 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003399 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 +01003400 file, linenum);
3401
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 }
3405 }
3406
3407 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003408 if (newsrv->trackit) {
3409 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3410 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003413 }
3414
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003415 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3416 newsrv->check_port = newsrv->check_addr.sin_port;
3417
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3419 newsrv->check_port = realport; /* by default */
3420 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003421 /* not yet valid, because no port was set on
3422 * the server either. We'll check if we have
3423 * a known port on the first listener.
3424 */
3425 struct listener *l;
3426 l = curproxy->listen;
3427 if (l) {
3428 int port;
3429 port = (l->addr.ss_family == AF_INET6)
3430 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3431 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3432 newsrv->check_port = port;
3433 }
3434 }
3435 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3437 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_ALERT | ERR_FATAL;
3439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003441
3442 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 newsrv->state |= SRV_CHECKED;
3444 }
3445
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003446 if (!defsrv) {
3447 if (newsrv->state & SRV_BACKUP)
3448 curproxy->srv_bck++;
3449 else
3450 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003451
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003452 newsrv->prev_state = newsrv->state;
3453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003454 }
3455 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003456 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 int facility;
3458
3459 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3460 curproxy->logfac1 = global.logfac1;
3461 curproxy->logsrv1 = global.logsrv1;
3462 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003463 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 curproxy->logfac2 = global.logfac2;
3465 curproxy->logsrv2 = global.logsrv2;
3466 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003467 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 }
3469 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003470 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471
3472 facility = get_log_facility(args[2]);
3473 if (facility < 0) {
3474 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3475 exit(1);
3476 }
3477
3478 level = 7; /* max syslog level = debug */
3479 if (*(args[3])) {
3480 level = get_log_level(args[3]);
3481 if (level < 0) {
3482 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3483 exit(1);
3484 }
3485 }
3486
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003487 minlvl = 0; /* limit syslog level to this level (emerg) */
3488 if (*(args[4])) {
3489 minlvl = get_log_level(args[4]);
3490 if (level < 0) {
3491 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3492 exit(1);
3493 }
3494 }
3495
Robert Tsai81ae1952007-12-05 10:47:29 +01003496 if (args[1][0] == '/') {
3497 logsrv.u.addr.sa_family = AF_UNIX;
3498 logsrv.u.un = *str2sun(args[1]);
3499 } else {
3500 logsrv.u.addr.sa_family = AF_INET;
3501 logsrv.u.in = *str2sa(args[1]);
3502 if (!logsrv.u.in.sin_port) {
3503 logsrv.u.in.sin_port =
3504 htons(SYSLOG_PORT);
3505 }
3506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507
3508 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003509 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 curproxy->logfac1 = facility;
3511 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003512 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
3514 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003515 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 curproxy->logfac2 = facility;
3517 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003518 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
3520 else {
3521 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 }
3525 }
3526 else {
3527 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 }
3532 }
3533 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003534 int cur_arg;
3535
Willy Tarreau977b8e42006-12-29 14:19:17 +01003536 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003538
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003540 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3541 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003545
3546 /* we must first clear any optional default setting */
3547 curproxy->options &= ~PR_O_TPXY_MASK;
3548 free(curproxy->iface_name);
3549 curproxy->iface_name = NULL;
3550 curproxy->iface_len = 0;
3551
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 curproxy->source_addr = *str2sa(args[1]);
3553 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003554
3555 cur_arg = 2;
3556 while (*(args[cur_arg])) {
3557 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003558#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3559#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003560 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3561 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3562 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003565 }
3566#endif
3567 if (!*args[cur_arg + 1]) {
3568 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3569 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003572 }
3573
3574 if (!strcmp(args[cur_arg + 1], "client")) {
3575 curproxy->options |= PR_O_TPXY_CLI;
3576 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3577 curproxy->options |= PR_O_TPXY_CIP;
3578 } else {
3579 curproxy->options |= PR_O_TPXY_ADDR;
3580 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3581 }
3582 global.last_checks |= LSTCHK_NETADM;
3583#if !defined(CONFIG_HAP_LINUX_TPROXY)
3584 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003585#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003586#else /* no TPROXY support */
3587 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003588 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003591#endif
3592 cur_arg += 2;
3593 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003594 }
3595
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003596 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3597#ifdef SO_BINDTODEVICE
3598 if (!*args[cur_arg + 1]) {
3599 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3600 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003603 }
3604 if (curproxy->iface_name)
3605 free(curproxy->iface_name);
3606
3607 curproxy->iface_name = strdup(args[cur_arg + 1]);
3608 curproxy->iface_len = strlen(curproxy->iface_name);
3609 global.last_checks |= LSTCHK_NETADM;
3610#else
3611 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3612 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003615#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003616 cur_arg += 2;
3617 continue;
3618 }
3619 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3620 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003625 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3626 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3627 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003632 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003638
3639 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3640 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003641 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003642 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
3645 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003646 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3647 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003648 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003649 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
3652 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003653 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3654 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003655 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003656 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 }
3659 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003660 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3661 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003662 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003663 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
3666 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003667 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3668 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003669 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003670 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003673 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003674 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3675 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003676 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003677 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003678 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003679 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003680 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003681 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3682 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01003683 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003684 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003685 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003686 }
3687 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003688 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3689 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003690 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003691 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003692 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003695 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01003701
3702 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3703 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003704 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003705 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 }
3708 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003709 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3710 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003711 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003712 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
3715 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003716 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3717 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003718 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003719 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003723 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3724 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003725 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003726 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
3729 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003730 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3731 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003732 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003733 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003736 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003737 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3738 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01003739 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003740 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003741 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003744 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003745
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 if (curproxy == &defproxy) {
3747 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754 if (*(args[1]) == 0) {
3755 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003759
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003760 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3761 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3762 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3763 file, linenum, args[0]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3768 }
3769 else if (*args[2]) {
3770 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3771 file, linenum, args[0], args[2]);
3772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
3774 }
3775
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003776 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01003777 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003778 wl->s = strdup(args[1]);
3779 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003780 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
3782 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response 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 Tarreau977b8e42006-12-29 14:19:17 +01003789
Willy Tarreauade5ec42010-01-28 19:33:49 +01003790 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3791 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3798 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003804 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3805 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003811 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3813 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
3817
Willy Tarreauade5ec42010-01-28 19:33:49 +01003818 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3819 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003820 args[0], args[1], args[2], (const char **)args+3);
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 }
3824 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003825 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3826 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 Tarreaubaaee002006-06-26 02:48:02 +02003830 }
3831 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01003832 err_code |= create_cond_regex_rule(file, linenum, curproxy,
3833 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003834 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01003835 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02003836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
3838 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01003839 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003840
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 if (curproxy == &defproxy) {
3842 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003846 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848
Willy Tarreaubaaee002006-06-26 02:48:02 +02003849 if (*(args[1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 }
3854
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003855 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
3856 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
3857 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
3858 file, linenum, args[0]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
3862 err_code |= warnif_cond_requires_req(cond, file, linenum);
3863 }
3864 else if (*args[2]) {
3865 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
3866 file, linenum, args[0], args[2]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003871 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01003872 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003873 wl->s = strdup(args[1]);
3874 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
3876 else if (!strcmp(args[0], "errorloc") ||
3877 !strcmp(args[0], "errorloc302") ||
3878 !strcmp(args[0], "errorloc303")) { /* error location */
3879 int errnum, errlen;
3880 char *err;
3881
Willy Tarreau977b8e42006-12-29 14:19:17 +01003882 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003884
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003886 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
3890
3891 errnum = atol(args[1]);
3892 if (!strcmp(args[0], "errorloc303")) {
3893 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3894 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3895 } else {
3896 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3897 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3898 }
3899
Willy Tarreau0f772532006-12-23 20:51:41 +01003900 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3901 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003902 chunk_destroy(&curproxy->errmsg[rc]);
3903 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003904 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003907
3908 if (rc >= HTTP_ERR_SIZE) {
3909 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3910 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 free(err);
3912 }
3913 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003914 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3915 int errnum, errlen, fd;
3916 char *err;
3917 struct stat stat;
3918
3919 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003921
3922 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003923 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003926 }
3927
3928 fd = open(args[2], O_RDONLY);
3929 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3930 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3931 file, linenum, args[2], args[1]);
3932 if (fd >= 0)
3933 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003936 }
3937
Willy Tarreau27a674e2009-08-17 07:23:33 +02003938 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003939 errlen = stat.st_size;
3940 } else {
3941 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003942 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003944 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003945 }
3946
3947 err = malloc(errlen); /* malloc() must succeed during parsing */
3948 errnum = read(fd, err, errlen);
3949 if (errnum != errlen) {
3950 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3951 file, linenum, args[2], args[1]);
3952 close(fd);
3953 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003956 }
3957 close(fd);
3958
3959 errnum = atol(args[1]);
3960 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3961 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003962 chunk_destroy(&curproxy->errmsg[rc]);
3963 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003964 break;
3965 }
3966 }
3967
3968 if (rc >= HTTP_ERR_SIZE) {
3969 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3970 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003972 free(err);
3973 }
3974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003976 struct cfg_kw_list *kwl;
3977 int index;
3978
3979 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3980 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3981 if (kwl->kw[index].section != CFG_LISTEN)
3982 continue;
3983 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3984 /* prepare error message just in case */
3985 snprintf(trash, sizeof(trash),
3986 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003987 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3988 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003989 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003992 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003993 else if (rc > 0) {
3994 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
3996 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003997 }
Willy Tarreau93893792009-07-23 13:19:11 +02003998 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003999 }
4000 }
4001 }
4002
Willy Tarreau6daf3432008-01-22 16:44:08 +01004003 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
Willy Tarreau93893792009-07-23 13:19:11 +02004007 out:
4008 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009}
4010
4011
4012/*
4013 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004014 * Returns the error code, 0 if OK, or any combination of :
4015 * - ERR_ABORT: must abort ASAP
4016 * - ERR_FATAL: we can continue parsing but not start the service
4017 * - ERR_WARN: a warning has been emitted
4018 * - ERR_ALERT: an alert has been emitted
4019 * Only the two first ones can stop processing, the two others are just
4020 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004022int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004024 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 FILE *f;
4026 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004028 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 if ((f=fopen(file,"r")) == NULL)
4031 return -1;
4032
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004033 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004034 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004035 char *end;
4036 char *args[MAX_LINE_ARGS + 1];
4037 char *line = thisline;
4038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 linenum++;
4040
4041 end = line + strlen(line);
4042
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004043 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4044 /* Check if we reached the limit and the last char is not \n.
4045 * Watch out for the last line without the terminating '\n'!
4046 */
4047 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004048 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004049 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004050 }
4051
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004053 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 line++;
4055
4056 arg = 0;
4057 args[arg] = line;
4058
4059 while (*line && arg < MAX_LINE_ARGS) {
4060 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4061 * C equivalent value. Other combinations left unchanged (eg: \1).
4062 */
4063 if (*line == '\\') {
4064 int skip = 0;
4065 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4066 *line = line[1];
4067 skip = 1;
4068 }
4069 else if (line[1] == 'r') {
4070 *line = '\r';
4071 skip = 1;
4072 }
4073 else if (line[1] == 'n') {
4074 *line = '\n';
4075 skip = 1;
4076 }
4077 else if (line[1] == 't') {
4078 *line = '\t';
4079 skip = 1;
4080 }
4081 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004082 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 unsigned char hex1, hex2;
4084 hex1 = toupper(line[2]) - '0';
4085 hex2 = toupper(line[3]) - '0';
4086 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4087 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4088 *line = (hex1<<4) + hex2;
4089 skip = 3;
4090 }
4091 else {
4092 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004094 }
4095 }
4096 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004097 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 end -= skip;
4099 }
4100 line++;
4101 }
4102 else if (*line == '#' || *line == '\n' || *line == '\r') {
4103 /* end of string, end of loop */
4104 *line = 0;
4105 break;
4106 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004107 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004109 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004110 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 line++;
4112 args[++arg] = line;
4113 }
4114 else {
4115 line++;
4116 }
4117 }
4118
4119 /* empty line */
4120 if (!**args)
4121 continue;
4122
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004123 if (*line) {
4124 /* we had to stop due to too many args.
4125 * Let's terminate the string, print the offending part then cut the
4126 * last arg.
4127 */
4128 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4129 line++;
4130 *line = '\0';
4131
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004132 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004133 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 args[arg] = line;
4136 }
4137
Willy Tarreau540abe42007-05-02 20:50:16 +02004138 /* zero out remaining args and ensure that at least one entry
4139 * is zeroed out.
4140 */
4141 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 args[arg] = line;
4143 }
4144
Willy Tarreau3842f002009-06-14 11:39:52 +02004145 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004146 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004147 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004148 for (arg=0; *args[arg+1]; arg++)
4149 args[arg] = args[arg+1]; // shift args after inversion
4150 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004151 else if (!strcmp(args[0], "default")) {
4152 kwm = KWM_DEF;
4153 for (arg=0; *args[arg+1]; arg++)
4154 args[arg] = args[arg+1]; // shift args after inversion
4155 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004156
Willy Tarreau3842f002009-06-14 11:39:52 +02004157 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4158 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004160 }
4161
Willy Tarreau977b8e42006-12-29 14:19:17 +01004162 if (!strcmp(args[0], "listen") ||
4163 !strcmp(args[0], "frontend") ||
4164 !strcmp(args[0], "backend") ||
4165 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004166 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004168 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004169 cursection = strdup(args[0]);
4170 }
4171 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004173 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004174 cursection = strdup(args[0]);
4175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 /* else it's a section keyword */
4177
4178 switch (confsect) {
4179 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 break;
4182 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004183 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 break;
4185 default:
4186 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004189
4190 if (err_code & ERR_ABORT)
4191 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004193 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004194 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004196 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004197}
4198
Willy Tarreaubb925012009-07-23 13:36:36 +02004199/*
4200 * Returns the error code, 0 if OK, or any combination of :
4201 * - ERR_ABORT: must abort ASAP
4202 * - ERR_FATAL: we can continue parsing but not start the service
4203 * - ERR_WARN: a warning has been emitted
4204 * - ERR_ALERT: an alert has been emitted
4205 * Only the two first ones can stop processing, the two others are just
4206 * indicators.
4207 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004208int check_config_validity()
4209{
4210 int cfgerr = 0;
4211 struct proxy *curproxy = NULL;
4212 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004213 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004214 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215
4216 /*
4217 * Now, check for the integrity of all that we have collected.
4218 */
4219
4220 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004221 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004223 /* first, we will invert the proxy list order */
4224 curproxy = NULL;
4225 while (proxy) {
4226 struct proxy *next;
4227
4228 next = proxy->next;
4229 proxy->next = curproxy;
4230 curproxy = proxy;
4231 if (!next)
4232 break;
4233 proxy = next;
4234 }
4235
Willy Tarreaubaaee002006-06-26 02:48:02 +02004236 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004237 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004240 }
4241
4242 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004243 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004244 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004245 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004246 unsigned int next_id;
4247
4248 if (!curproxy->uuid) {
4249 /* proxy ID not set, use automatic numbering with first
4250 * spare entry starting with next_pxid.
4251 */
4252 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4253 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4254 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4255 next_pxid++;
4256 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004257
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004259 /* ensure we don't keep listeners uselessly bound */
4260 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 curproxy = curproxy->next;
4262 continue;
4263 }
4264
Willy Tarreauff01a212009-03-15 13:46:16 +01004265 switch (curproxy->mode) {
4266 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004267 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004268 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004269 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4270 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004271 cfgerr++;
4272 }
4273
4274 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004275 Warning("config : servers will be ignored for %s '%s'.\n",
4276 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004277 break;
4278
4279 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004280 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004281 break;
4282
4283 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004284 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004285 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004286 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4287 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004288 cfgerr++;
4289 }
4290 break;
4291 }
4292
4293 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004294 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4295 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 cfgerr++;
4297 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004298
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004299 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004300 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004301 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004302 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4303 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004304 cfgerr++;
4305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004307 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004308 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4309 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004310 cfgerr++;
4311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004313 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004314 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4315 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004316 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004317 }
4318 }
4319 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4320 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4321 /* If no LB algo is set in a backend, and we're not in
4322 * transparent mode, dispatch mode nor proxy mode, we
4323 * want to use balance roundrobin by default.
4324 */
4325 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4326 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 }
4328 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004329
Willy Tarreau82936582007-11-30 15:20:09 +01004330 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4331 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004332 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4333 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004334 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004335 }
4336
Willy Tarreauef781042010-01-27 11:53:01 +01004337 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
4338 curproxy->options &= ~PR_O2_CHK_SNDST;
4339 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4340 "send-state", proxy_type_str(curproxy), curproxy->id);
4341 err_code |= ERR_WARN;
4342 }
4343
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004344 /* if a default backend was specified, let's find it */
4345 if (curproxy->defbe.name) {
4346 struct proxy *target;
4347
Alex Williams96532db2009-11-01 21:27:13 -05004348 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004349 if (!target) {
4350 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4351 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004352 cfgerr++;
4353 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004354 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4355 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004356 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004357 } else {
4358 free(curproxy->defbe.name);
4359 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004360 /* we force the backend to be present on at least all of
4361 * the frontend's processes.
4362 */
4363 target->bind_proc = curproxy->bind_proc ?
4364 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 }
4366 }
4367
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004368 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004369 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4370 /* map jump target for ACT_SETBE in req_rep chain */
4371 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004372 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004373 struct proxy *target;
4374
Willy Tarreaua496b602006-12-17 23:15:24 +01004375 if (exp->action != ACT_SETBE)
4376 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004377
Alex Williams96532db2009-11-01 21:27:13 -05004378 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004379 if (!target) {
4380 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4381 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004382 cfgerr++;
4383 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004384 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4385 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004386 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004387 } else {
4388 free((void *)exp->replace);
4389 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004390 /* we force the backend to be present on at least all of
4391 * the frontend's processes.
4392 */
4393 target->bind_proc = curproxy->bind_proc ?
4394 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004395 }
4396 }
4397 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004398
4399 /* find the target proxy for 'use_backend' rules */
4400 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004401 struct proxy *target;
4402
Alex Williams96532db2009-11-01 21:27:13 -05004403 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004404
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004405 if (!target) {
4406 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4407 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004408 cfgerr++;
4409 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004410 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4411 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004412 cfgerr++;
4413 } else {
4414 free((void *)rule->be.name);
4415 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004416 /* we force the backend to be present on at least all of
4417 * the frontend's processes.
4418 */
4419 target->bind_proc = curproxy->bind_proc ?
4420 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004421 }
4422 }
4423
Emeric Brunb982a3d2010-01-04 15:45:53 +01004424 /* find the target table for 'stick' rules */
4425 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4426 struct proxy *target;
4427
Emeric Brun1d33b292010-01-04 15:47:17 +01004428 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4429 if (mrule->flags & STK_IS_STORE)
4430 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4431
Emeric Brunb982a3d2010-01-04 15:45:53 +01004432 if (mrule->table.name)
4433 target = findproxy(mrule->table.name, PR_CAP_BE);
4434 else
4435 target = curproxy;
4436
4437 if (!target) {
4438 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4439 curproxy->id, mrule->table.name);
4440 cfgerr++;
4441 }
4442 else if (target->table.size == 0) {
4443 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4444 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4445 cfgerr++;
4446 }
4447 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4448 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4449 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4450 cfgerr++;
4451 }
4452 else {
4453 free((void *)mrule->table.name);
4454 mrule->table.t = &(target->table);
4455 }
4456 }
4457
4458 /* find the target table for 'store response' rules */
4459 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4460 struct proxy *target;
4461
Emeric Brun1d33b292010-01-04 15:47:17 +01004462 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4463
Emeric Brunb982a3d2010-01-04 15:45:53 +01004464 if (mrule->table.name)
4465 target = findproxy(mrule->table.name, PR_CAP_BE);
4466 else
4467 target = curproxy;
4468
4469 if (!target) {
4470 Alert("Proxy '%s': unable to find store table '%s'.\n",
4471 curproxy->id, mrule->table.name);
4472 cfgerr++;
4473 }
4474 else if (target->table.size == 0) {
4475 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4476 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4477 cfgerr++;
4478 }
4479 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4480 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4481 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4482 cfgerr++;
4483 }
4484 else {
4485 free((void *)mrule->table.name);
4486 mrule->table.t = &(target->table);
4487 }
4488 }
4489
Willy Tarreau2738a142006-07-08 17:28:09 +02004490 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004491 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004492 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004493 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004494 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004495 " | While not properly invalid, you will certainly encounter various problems\n"
4496 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004497 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004498 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004499 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004500 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004501
Willy Tarreau1fa31262007-12-03 00:36:16 +01004502 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4503 * We must still support older configurations, so let's find out whether those
4504 * parameters have been set or must be copied from contimeouts.
4505 */
4506 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004507 if (!curproxy->timeout.tarpit ||
4508 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004509 /* tarpit timeout not set. We search in the following order:
4510 * default.tarpit, curr.connect, default.connect.
4511 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004512 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004513 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004514 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004515 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004516 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004517 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004518 }
4519 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004520 (!curproxy->timeout.queue ||
4521 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004522 /* queue timeout not set. We search in the following order:
4523 * default.queue, curr.connect, default.connect.
4524 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004525 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004526 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004527 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004528 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004529 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004530 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004531 }
4532 }
4533
Willy Tarreauf3c69202006-07-09 16:42:34 +02004534 if (curproxy->options & PR_O_SSL3_CHK) {
4535 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4536 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4537 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4538 }
4539
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004540 /* The small pools required for the capture lists */
4541 if (curproxy->nb_req_cap)
4542 curproxy->req_cap_pool = create_pool("ptrcap",
4543 curproxy->nb_req_cap * sizeof(char *),
4544 MEM_F_SHARED);
4545 if (curproxy->nb_rsp_cap)
4546 curproxy->rsp_cap_pool = create_pool("ptrcap",
4547 curproxy->nb_rsp_cap * sizeof(char *),
4548 MEM_F_SHARED);
4549
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004550 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4551 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4552 MEM_F_SHARED);
4553
Willy Tarreau86034312006-12-29 00:10:33 +01004554 /* for backwards compatibility with "listen" instances, if
4555 * fullconn is not set but maxconn is set, then maxconn
4556 * is used.
4557 */
4558 if (!curproxy->fullconn)
4559 curproxy->fullconn = curproxy->maxconn;
4560
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 /* first, we will invert the servers list order */
4562 newsrv = NULL;
4563 while (curproxy->srv) {
4564 struct server *next;
4565
4566 next = curproxy->srv->next;
4567 curproxy->srv->next = newsrv;
4568 newsrv = curproxy->srv;
4569 if (!next)
4570 break;
4571 curproxy->srv = next;
4572 }
4573
Willy Tarreau20697042007-11-15 23:26:18 +01004574 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004575 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004577 /* We have to initialize the server lookup mechanism depending
4578 * on what LB algorithm was choosen.
4579 */
4580
4581 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4582 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4583 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004584 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4585 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4586 init_server_map(curproxy);
4587 } else {
4588 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4589 fwrr_init_server_groups(curproxy);
4590 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004591 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004592
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004593 case BE_LB_KIND_LC:
4594 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004595 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004596 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004597
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004598 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004599 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4600 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4601 chash_init_server_tree(curproxy);
4602 } else {
4603 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4604 init_server_map(curproxy);
4605 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004606 break;
4607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004608
4609 if (curproxy->options & PR_O_LOGASAP)
4610 curproxy->to_log &= ~LW_BYTES;
4611
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004612 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4613 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4614 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4615 proxy_type_str(curproxy), curproxy->id);
4616 err_code |= ERR_WARN;
4617 }
4618
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004620 * ensure that we're not cross-dressing a TCP server into HTTP.
4621 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004622 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004623 newsrv = curproxy->srv;
4624 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004625 if (!newsrv->puid) {
4626 /* server ID not set, use automatic numbering with first
4627 * spare entry starting with next_svid.
4628 */
4629 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4630 newsrv->conf.id.key = newsrv->puid = next_id;
4631 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4632 next_id++;
4633 }
4634
Willy Tarreau21d2af32008-02-14 20:25:24 +01004635 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004636 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4637 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004638 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004639 }
4640 newsrv = newsrv->next;
4641 }
4642
4643 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 * If this server supports a maxconn parameter, it needs a dedicated
4645 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004646 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 */
4648 newsrv = curproxy->srv;
4649 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004650 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 /* Only 'minconn' was specified, or it was higher than or equal
4652 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4653 * this will avoid further useless expensive computations.
4654 */
4655 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004656 } else if (newsrv->maxconn && !newsrv->minconn) {
4657 /* minconn was not specified, so we set it to maxconn */
4658 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004659 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004660 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4661 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004662 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663 }
4664
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004665 if (newsrv->trackit) {
4666 struct proxy *px;
4667 struct server *srv;
4668 char *pname, *sname;
4669
4670 pname = newsrv->trackit;
4671 sname = strrchr(pname, '/');
4672
4673 if (sname)
4674 *sname++ = '\0';
4675 else {
4676 sname = pname;
4677 pname = NULL;
4678 }
4679
4680 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004681 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004682 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004683 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4684 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004685 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004686 cfgerr++;
4687 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004688 }
4689 } else
4690 px = curproxy;
4691
4692 srv = findserver(px, sname);
4693 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004694 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4695 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004696 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004697 cfgerr++;
4698 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004699 }
4700
4701 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004702 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05004703 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004704 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004705 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004706 cfgerr++;
4707 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004708 }
4709
4710 if (curproxy != px &&
4711 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004712 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01004713 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004714 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004715 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004716 cfgerr++;
4717 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004718 }
4719
4720 newsrv->tracked = srv;
4721 newsrv->tracknext = srv->tracknext;
4722 srv->tracknext = newsrv;
4723
4724 free(newsrv->trackit);
4725 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004726 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 newsrv = newsrv->next;
4728 }
4729
Willy Tarreauc1a21672009-08-16 22:37:44 +02004730 if (curproxy->cap & PR_CAP_FE) {
4731 if (curproxy->tcp_req.inspect_delay ||
4732 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4733 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4734
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004735 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004736 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004737 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004738 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004739
4740 /* both TCP and HTTP must check switching rules */
4741 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4742 }
4743
4744 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004745 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004746 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02004747 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004748 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004749
Emeric Brunb982a3d2010-01-04 15:45:53 +01004750 /* init table on backend capabilities proxy */
4751 stktable_init(&curproxy->table);
4752
Willy Tarreauc1a21672009-08-16 22:37:44 +02004753 /* If the backend does requires RDP cookie persistence, we have to
4754 * enable the corresponding analyser.
4755 */
4756 if (curproxy->options2 & PR_O2_RDPC_PRST)
4757 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4758 }
4759
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004760 listener = NULL;
4761 while (curproxy->listen) {
4762 struct listener *next;
4763
4764 next = curproxy->listen->next;
4765 curproxy->listen->next = listener;
4766 listener = curproxy->listen;
4767
4768 if (!next)
4769 break;
4770
4771 curproxy->listen = next;
4772 }
4773
Willy Tarreaue6b98942007-10-29 01:09:36 +01004774 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004775 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004776 listener = curproxy->listen;
4777 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004778 if (!listener->luid) {
4779 /* listener ID not set, use automatic numbering with first
4780 * spare entry starting with next_luid.
4781 */
4782 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
4783 listener->conf.id.key = listener->luid = next_id;
4784 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
4785 next_id++;
4786 }
4787
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02004788 /* enable separate counters */
4789 if (curproxy->options2 & PR_O2_SOCKSTAT) {
4790 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
4791 if (!listener->name) {
4792 sprintf(trash, "sock-%d", listener->luid);
4793 listener->name = strdup(trash);
4794 }
4795 }
4796
Willy Tarreaue6b98942007-10-29 01:09:36 +01004797 if (curproxy->options & PR_O_TCP_NOLING)
4798 listener->options |= LI_O_NOLINGER;
4799 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004800 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004801 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004802 listener->accept = event_accept;
4803 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004804 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004805 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004806
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004807 /* smart accept mode is automatic in HTTP mode */
4808 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4809 (curproxy->mode == PR_MODE_HTTP &&
4810 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4811 listener->options |= LI_O_NOQUICKACK;
4812
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004813 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004814 listener = listener->next;
4815 }
4816
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 curproxy = curproxy->next;
4818 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004819
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004820 /*
4821 * Recount currently required checks.
4822 */
4823
4824 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4825 int optnum;
4826
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004827 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4828 if (curproxy->options & cfg_opts[optnum].val)
4829 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004830
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004831 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4832 if (curproxy->options2 & cfg_opts2[optnum].val)
4833 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004834 }
4835
Willy Tarreaubb925012009-07-23 13:36:36 +02004836 if (cfgerr > 0)
4837 err_code |= ERR_ALERT | ERR_FATAL;
4838 out:
4839 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840}
4841
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004842/*
4843 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4844 * parsing sessions.
4845 */
4846void cfg_register_keywords(struct cfg_kw_list *kwl)
4847{
4848 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4849}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004851/*
4852 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4853 */
4854void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4855{
4856 LIST_DEL(&kwl->list);
4857 LIST_INIT(&kwl->list);
4858}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859
4860/*
4861 * Local variables:
4862 * c-indent-level: 8
4863 * c-basic-offset: 8
4864 * End:
4865 */