blob: 84b99fe26cdea2779e9b9235e69b802262a80608 [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 */
282int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
283{
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 */
305int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
306{
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 */
318int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
319{
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 */
331int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
332{
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 */
344int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
345{
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 */
357int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
358{
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 */
368int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
369{
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 */
377int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
378{
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 */
385int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
386{
387 return warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
Willy Tarreaubaaee002006-06-26 02:48:02 +0200391/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200392 * parse a line in a <global> section. Returns the error code, 0 if OK, or
393 * any combination of :
394 * - ERR_ABORT: must abort ASAP
395 * - ERR_FATAL: we can continue parsing but not start the service
396 * - ERR_WARN: a warning has been emitted
397 * - ERR_ALERT: an alert has been emitted
398 * Only the two first ones can stop processing, the two others are just
399 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200401int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200402{
Willy Tarreau058e9072009-07-20 09:30:05 +0200403 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200404
405 if (!strcmp(args[0], "global")) { /* new section */
406 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200408 }
409 else if (!strcmp(args[0], "daemon")) {
410 global.mode |= MODE_DAEMON;
411 }
412 else if (!strcmp(args[0], "debug")) {
413 global.mode |= MODE_DEBUG;
414 }
415 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100416 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200417 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200418 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100419 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200420 }
421 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100422 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200424 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100425 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100427 else if (!strcmp(args[0], "nosplice")) {
428 global.tune.options &= ~GTUNE_USE_SPLICE;
429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200430 else if (!strcmp(args[0], "quiet")) {
431 global.mode |= MODE_QUIET;
432 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200433 else if (!strcmp(args[0], "tune.maxpollevents")) {
434 if (global.tune.maxpollevents != 0) {
435 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200436 err_code |= ERR_ALERT;
437 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200438 }
439 if (*(args[1]) == 0) {
440 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200441 err_code |= ERR_ALERT | ERR_FATAL;
442 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200443 }
444 global.tune.maxpollevents = atol(args[1]);
445 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100446 else if (!strcmp(args[0], "tune.maxaccept")) {
447 if (global.tune.maxaccept != 0) {
448 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200449 err_code |= ERR_ALERT;
450 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100451 }
452 if (*(args[1]) == 0) {
453 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 err_code |= ERR_ALERT | ERR_FATAL;
455 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100456 }
457 global.tune.maxaccept = atol(args[1]);
458 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200459 else if (!strcmp(args[0], "tune.bufsize")) {
460 if (*(args[1]) == 0) {
461 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
462 err_code |= ERR_ALERT | ERR_FATAL;
463 goto out;
464 }
465 global.tune.bufsize = atol(args[1]);
466 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
467 global.tune.maxrewrite = global.tune.bufsize / 2;
468 }
469 else if (!strcmp(args[0], "tune.maxrewrite")) {
470 if (*(args[1]) == 0) {
471 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT | ERR_FATAL;
473 goto out;
474 }
475 global.tune.maxrewrite = atol(args[1]);
476 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
477 global.tune.maxrewrite = global.tune.bufsize / 2;
478 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100479 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
480 if (global.tune.client_rcvbuf != 0) {
481 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
482 err_code |= ERR_ALERT;
483 goto out;
484 }
485 if (*(args[1]) == 0) {
486 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489 }
490 global.tune.client_rcvbuf = atol(args[1]);
491 }
492 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
493 if (global.tune.server_rcvbuf != 0) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.tune.server_rcvbuf = atol(args[1]);
504 }
505 else if (!strcmp(args[0], "tune.sndbuf.client")) {
506 if (global.tune.client_sndbuf != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT;
509 goto out;
510 }
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.client_sndbuf = atol(args[1]);
517 }
518 else if (!strcmp(args[0], "tune.sndbuf.server")) {
519 if (global.tune.server_sndbuf != 0) {
520 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT;
522 goto out;
523 }
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.server_sndbuf = atol(args[1]);
530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531 else if (!strcmp(args[0], "uid")) {
532 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200533 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541 }
542 global.uid = atol(args[1]);
543 }
544 else if (!strcmp(args[0], "gid")) {
545 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200546 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 }
555 global.gid = atol(args[1]);
556 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200557 /* user/group name handling */
558 else if (!strcmp(args[0], "user")) {
559 struct passwd *ha_user;
560 if (global.uid != 0) {
561 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200562 err_code |= ERR_ALERT;
563 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200564 }
565 errno = 0;
566 ha_user = getpwnam(args[1]);
567 if (ha_user != NULL) {
568 global.uid = (int)ha_user->pw_uid;
569 }
570 else {
571 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 +0200572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200573 }
574 }
575 else if (!strcmp(args[0], "group")) {
576 struct group *ha_group;
577 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200578 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT;
580 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200581 }
582 errno = 0;
583 ha_group = getgrnam(args[1]);
584 if (ha_group != NULL) {
585 global.gid = (int)ha_group->gr_gid;
586 }
587 else {
588 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 +0200589 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200590 }
591 }
592 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 else if (!strcmp(args[0], "nbproc")) {
594 if (global.nbproc != 0) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200596 err_code |= ERR_ALERT;
597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 }
604 global.nbproc = atol(args[1]);
605 }
606 else if (!strcmp(args[0], "maxconn")) {
607 if (global.maxconn != 0) {
608 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200609 err_code |= ERR_ALERT;
610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 }
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 }
617 global.maxconn = atol(args[1]);
618#ifdef SYSTEM_MAXCONN
619 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
620 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);
621 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624#endif /* SYSTEM_MAXCONN */
625 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100626 else if (!strcmp(args[0], "maxpipes")) {
627 if (global.maxpipes != 0) {
628 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100636 }
637 global.maxpipes = atol(args[1]);
638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 else if (!strcmp(args[0], "ulimit-n")) {
640 if (global.rlimit_nofile != 0) {
641 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200642 err_code |= ERR_ALERT;
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
645 if (*(args[1]) == 0) {
646 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 global.rlimit_nofile = atol(args[1]);
651 }
652 else if (!strcmp(args[0], "chroot")) {
653 if (global.chroot != NULL) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.chroot = strdup(args[1]);
664 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200665 else if (!strcmp(args[0], "description")) {
666 int i, len=0;
667 char *d;
668
669 if (!*args[1]) {
670 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
671 file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675
676 for(i=1; *args[i]; i++)
677 len += strlen(args[i])+1;
678
679 if (global.desc)
680 free(global.desc);
681
682 global.desc = d = (char *)calloc(1, len);
683
684 d += sprintf(d, "%s", args[1]);
685 for(i=2; *args[i]; i++)
686 d += sprintf(d, " %s", args[i]);
687 }
688 else if (!strcmp(args[0], "node")) {
689 int i;
690 char c;
691
692 for (i=0; args[1][i]; i++) {
693 c = args[1][i];
694 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
695 break;
696 }
697
698 if (!i || args[1][i]) {
699 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
700 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
701 file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705
706 if (global.node)
707 free(global.node);
708
709 global.node = strdup(args[1]);
710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 else if (!strcmp(args[0], "pidfile")) {
712 if (global.pidfile != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.pidfile = strdup(args[1]);
723 }
724 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100725 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200726 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727
728 if (*(args[1]) == 0 || *(args[2]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733
734 facility = get_log_facility(args[2]);
735 if (facility < 0) {
736 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740
741 level = 7; /* max syslog level = debug */
742 if (*(args[3])) {
743 level = get_log_level(args[3]);
744 if (level < 0) {
745 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200746 err_code |= ERR_ALERT | ERR_FATAL;
747 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748 }
749 }
750
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200751 minlvl = 0; /* limit syslog level to this level (emerg) */
752 if (*(args[4])) {
753 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200754 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200755 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200758 }
759 }
760
Robert Tsai81ae1952007-12-05 10:47:29 +0100761 if (args[1][0] == '/') {
762 logsrv.u.addr.sa_family = AF_UNIX;
763 logsrv.u.un = *str2sun(args[1]);
764 } else {
765 logsrv.u.addr.sa_family = AF_INET;
766 logsrv.u.in = *str2sa(args[1]);
767 if (!logsrv.u.in.sin_port)
768 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770
771 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100772 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 global.logfac1 = facility;
774 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200775 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100778 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 global.logfac2 = facility;
780 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200781 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 else {
784 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200787 }
788 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
789 if (global.spread_checks != 0) {
790 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT;
792 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200798 }
799 global.spread_checks = atol(args[1]);
800 if (global.spread_checks < 0 || global.spread_checks > 50) {
801 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200806 struct cfg_kw_list *kwl;
807 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200808 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200809
810 list_for_each_entry(kwl, &cfg_keywords.list, list) {
811 for (index = 0; kwl->kw[index].kw != NULL; index++) {
812 if (kwl->kw[index].section != CFG_GLOBAL)
813 continue;
814 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
815 /* prepare error message just in case */
816 snprintf(trash, sizeof(trash),
817 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200818 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
819 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200820 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200822 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200823 else if (rc > 0) {
824 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_WARN;
826 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200827 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200828 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200829 }
830 }
831 }
832
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200836
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 out:
838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839}
840
Willy Tarreau97cb7802010-01-03 20:23:58 +0100841/* Perform the most basic initialization of a proxy :
842 * memset(), list_init(*), reset_timeouts(*).
843 */
844static void init_new_proxy(struct proxy *p)
845{
846 memset(p, 0, sizeof(struct proxy));
847 LIST_INIT(&p->pendconns);
848 LIST_INIT(&p->acl);
849 LIST_INIT(&p->block_cond);
850 LIST_INIT(&p->redirect_rules);
851 LIST_INIT(&p->mon_fail_cond);
852 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100853 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100854 LIST_INIT(&p->sticking_rules);
855 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100856 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100857 LIST_INIT(&p->req_add);
858 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100859
860 /* Timeouts are defined as -1 */
861 proxy_reset_timeouts(p);
862}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200864void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200865{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100866 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 defproxy.mode = PR_MODE_TCP;
868 defproxy.state = PR_STNEW;
869 defproxy.maxconn = cfg_maxpconn;
870 defproxy.conn_retries = CONN_RETRIES;
871 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100872
873 defproxy.defsrv.inter = DEF_CHKINTR;
874 defproxy.defsrv.fastinter = 0;
875 defproxy.defsrv.downinter = 0;
876 defproxy.defsrv.rise = DEF_RISETIME;
877 defproxy.defsrv.fall = DEF_FALLTIME;
878 defproxy.defsrv.check_port = 0;
879 defproxy.defsrv.maxqueue = 0;
880 defproxy.defsrv.minconn = 0;
881 defproxy.defsrv.maxconn = 0;
882 defproxy.defsrv.slowstart = 0;
883 defproxy.defsrv.onerror = DEF_HANA_ONERR;
884 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
885 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886}
887
888/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100889 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200890 * Returns the error code, 0 if OK, or any combination of :
891 * - ERR_ABORT: must abort ASAP
892 * - ERR_FATAL: we can continue parsing but not start the service
893 * - ERR_WARN: a warning has been emitted
894 * - ERR_ALERT: an alert has been emitted
895 * Only the two first ones can stop processing, the two others are just
896 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200898int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899{
900 static struct proxy *curproxy = NULL;
901 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200902 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100903 int rc;
904 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200905 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906
Willy Tarreau977b8e42006-12-29 14:19:17 +0100907 if (!strcmp(args[0], "listen"))
908 rc = PR_CAP_LISTEN;
909 else if (!strcmp(args[0], "frontend"))
910 rc = PR_CAP_FE | PR_CAP_RS;
911 else if (!strcmp(args[0], "backend"))
912 rc = PR_CAP_BE | PR_CAP_RS;
913 else if (!strcmp(args[0], "ruleset"))
914 rc = PR_CAP_RS;
915 else
916 rc = PR_CAP_NONE;
917
918 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (!*args[1]) {
920 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
921 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200923 err_code |= ERR_ALERT | ERR_ABORT;
924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200926
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100927 err = invalid_char(args[1]);
928 if (err) {
929 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
930 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100932 }
933
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200934 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
935 /*
936 * If there are two proxies with the same name only following
937 * combinations are allowed:
938 *
939 * listen backend frontend ruleset
940 * listen - - - -
941 * backend - - OK -
942 * frontend - OK - -
943 * ruleset - - - -
944 */
945
946 if (!strcmp(curproxy->id, args[1]) &&
947 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
948 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200949 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
950 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
951 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200952 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200953 }
954 }
955
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
957 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200958 err_code |= ERR_ALERT | ERR_ABORT;
959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100961
Willy Tarreau97cb7802010-01-03 20:23:58 +0100962 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 curproxy->next = proxy;
964 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200965 curproxy->conf.file = file;
966 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200967 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100969 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970
971 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200973 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200974 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200975 err_code |= ERR_FATAL;
976 goto out;
977 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200978 new = curproxy->listen;
979 while (new != last) {
980 new->conf.file = file;
981 new->conf.line = linenum;
982 new = new->next;
983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984 global.maxsock++;
985 }
986
987 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100988 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
989
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100992 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200993 curproxy->no_options = defproxy.no_options;
994 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100995 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100996 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200997 curproxy->except_net = defproxy.except_net;
998 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200999 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001000 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001002 if (defproxy.fwdfor_hdr_len) {
1003 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1004 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1005 }
1006
Willy Tarreaub86db342009-11-30 11:50:16 +01001007 if (defproxy.orgto_hdr_len) {
1008 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1009 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1010 }
1011
Willy Tarreau977b8e42006-12-29 14:19:17 +01001012 if (curproxy->cap & PR_CAP_FE) {
1013 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001014 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001015 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001016
1017 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001018 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1019 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001020
1021 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023
Willy Tarreau977b8e42006-12-29 14:19:17 +01001024 if (curproxy->cap & PR_CAP_BE) {
1025 curproxy->fullconn = defproxy.fullconn;
1026 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027
Willy Tarreau977b8e42006-12-29 14:19:17 +01001028 if (defproxy.check_req)
1029 curproxy->check_req = strdup(defproxy.check_req);
1030 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031
Willy Tarreau977b8e42006-12-29 14:19:17 +01001032 if (defproxy.cookie_name)
1033 curproxy->cookie_name = strdup(defproxy.cookie_name);
1034 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001035 if (defproxy.cookie_domain)
1036 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001037
Emeric Brun647caf12009-06-30 17:57:00 +02001038 if (defproxy.rdp_cookie_name)
1039 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1040 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1041
Willy Tarreau01732802007-11-01 22:48:15 +01001042 if (defproxy.url_param_name)
1043 curproxy->url_param_name = strdup(defproxy.url_param_name);
1044 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001045
Benoitaffb4812009-03-25 13:02:10 +01001046 if (defproxy.hh_name)
1047 curproxy->hh_name = strdup(defproxy.hh_name);
1048 curproxy->hh_len = defproxy.hh_len;
1049 curproxy->hh_match_domain = defproxy.hh_match_domain;
1050
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001051 if (defproxy.iface_name)
1052 curproxy->iface_name = strdup(defproxy.iface_name);
1053 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001056 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001057 if (defproxy.capture_name)
1058 curproxy->capture_name = strdup(defproxy.capture_name);
1059 curproxy->capture_namelen = defproxy.capture_namelen;
1060 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062
Willy Tarreau977b8e42006-12-29 14:19:17 +01001063 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001064 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001065 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001066 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001067 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001068 curproxy->uri_auth = defproxy.uri_auth;
1069 curproxy->mon_net = defproxy.mon_net;
1070 curproxy->mon_mask = defproxy.mon_mask;
1071 if (defproxy.monitor_uri)
1072 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1073 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001074 if (defproxy.defbe.name)
1075 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001076 }
1077
1078 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001079 curproxy->timeout.connect = defproxy.timeout.connect;
1080 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001081 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001082 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001083 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001084 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001085 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001086 curproxy->source_addr = defproxy.source_addr;
1087 }
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 curproxy->mode = defproxy.mode;
1090 curproxy->logfac1 = defproxy.logfac1;
1091 curproxy->logsrv1 = defproxy.logsrv1;
1092 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001093 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 curproxy->logfac2 = defproxy.logfac2;
1095 curproxy->logsrv2 = defproxy.logsrv2;
1096 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001097 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001099 curproxy->conf.used_listener_id = EB_ROOT;
1100 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001101
Willy Tarreau93893792009-07-23 13:19:11 +02001102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1105 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001106 /* FIXME-20070101: we should do this too at the end of the
1107 * config parsing to free all default values.
1108 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001109 free(defproxy.check_req);
1110 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001111 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001112 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001113 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001114 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001115 free(defproxy.capture_name);
1116 free(defproxy.monitor_uri);
1117 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001118 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001119 free(defproxy.fwdfor_hdr_name);
1120 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001121 free(defproxy.orgto_hdr_name);
1122 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001123
Willy Tarreaua534fea2008-08-03 12:19:50 +02001124 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001125 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001126
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 /* we cannot free uri_auth because it might already be used */
1128 init_default_instance();
1129 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001130 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 else if (curproxy == NULL) {
1134 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001137 }
1138
Willy Tarreau977b8e42006-12-29 14:19:17 +01001139
1140 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001142 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001143 int cur_arg;
1144
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 if (curproxy == &defproxy) {
1146 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001150 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001151 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152
1153 if (strchr(args[1], ':') == NULL) {
1154 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001159
1160 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001161 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001162 err_code |= ERR_ALERT | ERR_FATAL;
1163 goto out;
1164 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001165
Willy Tarreau90a570f2009-10-04 20:54:54 +02001166 new_listen = curproxy->listen;
1167 while (new_listen != last_listen) {
1168 new_listen->conf.file = file;
1169 new_listen->conf.line = linenum;
1170 new_listen = new_listen->next;
1171 }
1172
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001173 cur_arg = 2;
1174 while (*(args[cur_arg])) {
1175 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1176#ifdef SO_BINDTODEVICE
1177 struct listener *l;
1178
1179 if (!*args[cur_arg + 1]) {
1180 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001184 }
1185
1186 for (l = curproxy->listen; l != last_listen; l = l->next)
1187 l->interface = strdup(args[cur_arg + 1]);
1188
1189 global.last_checks |= LSTCHK_NETADM;
1190
1191 cur_arg += 2;
1192 continue;
1193#else
1194 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1195 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001198#endif
1199 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001200 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1201#ifdef TCP_MAXSEG
1202 struct listener *l;
1203 int mss;
1204
1205 if (!*args[cur_arg + 1]) {
1206 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001210 }
1211
1212 mss = str2uic(args[cur_arg + 1]);
1213 if (mss < 1 || mss > 65535) {
1214 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001218 }
1219
1220 for (l = curproxy->listen; l != last_listen; l = l->next)
1221 l->maxseg = mss;
1222
1223 cur_arg += 2;
1224 continue;
1225#else
1226 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1227 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001230#endif
1231 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001232
1233 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1234#ifdef TCP_DEFER_ACCEPT
1235 struct listener *l;
1236
1237 for (l = curproxy->listen; l != last_listen; l = l->next)
1238 l->options |= LI_O_DEF_ACCEPT;
1239
1240 cur_arg ++;
1241 continue;
1242#else
1243 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1244 file, linenum, args[0], args[cur_arg]);
1245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
1247#endif
1248 }
1249
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001250 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001251#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001252 struct listener *l;
1253
1254 for (l = curproxy->listen; l != last_listen; l = l->next)
1255 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001256
1257 cur_arg ++;
1258 continue;
1259#else
1260 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1261 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001264#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001265 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001266
1267 if (!strcmp(args[cur_arg], "name")) {
1268 struct listener *l;
1269
1270 for (l = curproxy->listen; l != last_listen; l = l->next)
1271 l->name = strdup(args[cur_arg + 1]);
1272
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001278 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001279 struct listener *l;
1280
1281 if (curproxy->listen->next != last_listen) {
1282 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1283 file, linenum, args[cur_arg]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287
1288 if (!*args[cur_arg + 1]) {
1289 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1290 file, linenum, args[cur_arg]);
1291 err_code |= ERR_ALERT | ERR_FATAL;
1292 goto out;
1293 }
1294
1295 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001296 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001297
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001298 if (curproxy->listen->luid <= 0) {
1299 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001300 file, linenum);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001305 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1306 if (node) {
1307 l = container_of(node, struct listener, conf.id);
1308 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1309 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
1312 }
1313 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1314
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001315 cur_arg += 2;
1316 continue;
1317 }
1318
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001319 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 +01001320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 }
1327 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1328 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1329 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001334 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001335 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336
Willy Tarreaubaaee002006-06-26 02:48:02 +02001337 /* flush useless bits */
1338 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001341 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001342 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001344
Willy Tarreau1c47f852006-07-09 08:22:27 +02001345 if (!*args[1]) {
1346 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001350 }
1351
Willy Tarreaua534fea2008-08-03 12:19:50 +02001352 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001353 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001354 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001355 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001356 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1357
Willy Tarreau93893792009-07-23 13:19:11 +02001358 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1361 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1362 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1363 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1364 else {
1365 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
1369 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001370 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001371 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001372
1373 if (curproxy == &defproxy) {
1374 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001378 }
1379
1380 if (!*args[1]) {
1381 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001385 }
1386
1387 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001388 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001389
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001390 if (curproxy->uuid <= 0) {
1391 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001392 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001395 }
1396
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001397 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1398 if (node) {
1399 struct proxy *target = container_of(node, struct proxy, conf.id);
1400 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1401 file, linenum, proxy_type_str(curproxy), curproxy->id,
1402 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1403 err_code |= ERR_ALERT | ERR_FATAL;
1404 goto out;
1405 }
1406 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001407 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001408 else if (!strcmp(args[0], "description")) {
1409 int i, len=0;
1410 char *d;
1411
Cyril Bonté99ed3272010-01-24 23:29:44 +01001412 if (curproxy == &defproxy) {
1413 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1414 file, linenum, args[0]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto out;
1417 }
1418
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001419 if (!*args[1]) {
1420 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1421 file, linenum, args[0]);
1422 return -1;
1423 }
1424
1425 for(i=1; *args[i]; i++)
1426 len += strlen(args[i])+1;
1427
1428 d = (char *)calloc(1, len);
1429 curproxy->desc = d;
1430
1431 d += sprintf(d, "%s", args[1]);
1432 for(i=2; *args[i]; i++)
1433 d += sprintf(d, " %s", args[i]);
1434
1435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1437 curproxy->state = PR_STSTOPPED;
1438 }
1439 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1440 curproxy->state = PR_STNEW;
1441 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001442 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1443 int cur_arg = 1;
1444 unsigned int set = 0;
1445
1446 while (*args[cur_arg]) {
1447 int u;
1448 if (strcmp(args[cur_arg], "all") == 0) {
1449 set = 0;
1450 break;
1451 }
1452 else if (strcmp(args[cur_arg], "odd") == 0) {
1453 set |= 0x55555555;
1454 }
1455 else if (strcmp(args[cur_arg], "even") == 0) {
1456 set |= 0xAAAAAAAA;
1457 }
1458 else {
1459 u = str2uic(args[cur_arg]);
1460 if (u < 1 || u > 32) {
1461 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1462 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001463 err_code |= ERR_ALERT | ERR_FATAL;
1464 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001465 }
1466 if (u > global.nbproc) {
1467 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001469 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001470 }
1471 set |= 1 << (u - 1);
1472 }
1473 cur_arg++;
1474 }
1475 curproxy->bind_proc = set;
1476 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001477 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001478 if (curproxy == &defproxy) {
1479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001482 }
1483
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001484 err = invalid_char(args[1]);
1485 if (err) {
1486 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1487 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001488 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001489 }
1490
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001491 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1492 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1493 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001494 err_code |= ERR_ALERT | ERR_FATAL;
1495 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001496 }
1497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1499 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 if (*(args[1]) == 0) {
1505 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001507 err_code |= ERR_ALERT | ERR_FATAL;
1508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001510
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001511 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001512 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001513 curproxy->cookie_name = strdup(args[1]);
1514 curproxy->cookie_len = strlen(curproxy->cookie_name);
1515
1516 cur_arg = 2;
1517 while (*(args[cur_arg])) {
1518 if (!strcmp(args[cur_arg], "rewrite")) {
1519 curproxy->options |= PR_O_COOK_RW;
1520 }
1521 else if (!strcmp(args[cur_arg], "indirect")) {
1522 curproxy->options |= PR_O_COOK_IND;
1523 }
1524 else if (!strcmp(args[cur_arg], "insert")) {
1525 curproxy->options |= PR_O_COOK_INS;
1526 }
1527 else if (!strcmp(args[cur_arg], "nocache")) {
1528 curproxy->options |= PR_O_COOK_NOC;
1529 }
1530 else if (!strcmp(args[cur_arg], "postonly")) {
1531 curproxy->options |= PR_O_COOK_POST;
1532 }
1533 else if (!strcmp(args[cur_arg], "prefix")) {
1534 curproxy->options |= PR_O_COOK_PFX;
1535 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001536 else if (!strcmp(args[cur_arg], "domain")) {
1537 if (!*args[cur_arg + 1]) {
1538 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1539 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001542 }
1543
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001544 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001545 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001546 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1547 " dots nor does not start with a dot."
1548 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001549 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001550 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001551 }
1552
1553 err = invalid_domainchar(args[cur_arg + 1]);
1554 if (err) {
1555 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1556 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
1558 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001559 }
1560
Willy Tarreau68a897b2009-12-03 23:28:34 +01001561 if (!curproxy->cookie_domain) {
1562 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1563 } else {
1564 /* one domain was already specified, add another one by
1565 * building the string which will be returned along with
1566 * the cookie.
1567 */
1568 char *new_ptr;
1569 int new_len = strlen(curproxy->cookie_domain) +
1570 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1571 new_ptr = malloc(new_len);
1572 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1573 free(curproxy->cookie_domain);
1574 curproxy->cookie_domain = new_ptr;
1575 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001576 cur_arg++;
1577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001579 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001581 err_code |= ERR_ALERT | ERR_FATAL;
1582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 }
1584 cur_arg++;
1585 }
1586 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1587 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1588 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001589 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
1591
1592 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1593 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1594 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
1597 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001598 else if (!strcmp(args[0], "persist")) { /* persist */
1599 if (*(args[1]) == 0) {
1600 Alert("parsing [%s:%d] : missing persist method.\n",
1601 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001602 err_code |= ERR_ALERT | ERR_FATAL;
1603 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001604 }
1605
1606 if (!strncmp(args[1], "rdp-cookie", 10)) {
1607 curproxy->options2 |= PR_O2_RDPC_PRST;
1608
Emeric Brunb982a3d2010-01-04 15:45:53 +01001609 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001610 const char *beg, *end;
1611
1612 beg = args[1] + 11;
1613 end = strchr(beg, ')');
1614
1615 if (!end || end == beg) {
1616 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1617 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001620 }
1621
1622 free(curproxy->rdp_cookie_name);
1623 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1624 curproxy->rdp_cookie_len = end-beg;
1625 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001626 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001627 free(curproxy->rdp_cookie_name);
1628 curproxy->rdp_cookie_name = strdup("msts");
1629 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1630 }
1631 else { /* syntax */
1632 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1633 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001636 }
1637 }
1638 else {
1639 Alert("parsing [%s:%d] : unknown persist method.\n",
1640 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001643 }
1644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001646 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001648 if (curproxy == &defproxy) {
1649 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001656
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001658 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 }
1663 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001664 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 curproxy->appsession_name = strdup(args[1]);
1666 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1667 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001668 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1669 if (err) {
1670 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1671 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001674 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001675 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001676
Willy Tarreau51041c72007-09-09 21:56:53 +02001677 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1678 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_ALERT | ERR_ABORT;
1680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001682
1683 cur_arg = 6;
1684 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001685 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1686 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001687 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001688 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001689 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001690 } else if (!strcmp(args[cur_arg], "prefix")) {
1691 curproxy->options2 |= PR_O2_AS_PFX;
1692 } else if (!strcmp(args[cur_arg], "mode")) {
1693 if (!*args[cur_arg + 1]) {
1694 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1695 file, linenum, args[0], args[cur_arg]);
1696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
1698 }
1699
1700 cur_arg++;
1701 if (!strcmp(args[cur_arg], "query-string")) {
1702 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1703 curproxy->options2 |= PR_O2_AS_M_QS;
1704 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1705 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1706 curproxy->options2 |= PR_O2_AS_M_PP;
1707 } else {
1708 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001713 cur_arg++;
1714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 } /* Url App Session */
1716 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001717 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01001721 if (curproxy == &defproxy) {
1722 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 if (*(args[4]) == 0) {
1728 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001733 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 curproxy->capture_name = strdup(args[2]);
1735 curproxy->capture_namelen = strlen(curproxy->capture_name);
1736 curproxy->capture_len = atol(args[4]);
1737 if (curproxy->capture_len >= CAPTURE_LEN) {
1738 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1739 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001740 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 curproxy->capture_len = CAPTURE_LEN - 1;
1742 }
1743 curproxy->to_log |= LW_COOKIE;
1744 }
1745 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1746 struct cap_hdr *hdr;
1747
1748 if (curproxy == &defproxy) {
1749 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 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 }
1753
1754 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1755 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1756 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 }
1760
1761 hdr = calloc(sizeof(struct cap_hdr), 1);
1762 hdr->next = curproxy->req_cap;
1763 hdr->name = strdup(args[3]);
1764 hdr->namelen = strlen(args[3]);
1765 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001766 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 hdr->index = curproxy->nb_req_cap++;
1768 curproxy->req_cap = hdr;
1769 curproxy->to_log |= LW_REQHDR;
1770 }
1771 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1772 struct cap_hdr *hdr;
1773
1774 if (curproxy == &defproxy) {
1775 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 +02001776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 }
1779
1780 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1781 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1782 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 }
1786 hdr = calloc(sizeof(struct cap_hdr), 1);
1787 hdr->next = curproxy->rsp_cap;
1788 hdr->name = strdup(args[3]);
1789 hdr->namelen = strlen(args[3]);
1790 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001791 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 hdr->index = curproxy->nb_rsp_cap++;
1793 curproxy->rsp_cap = hdr;
1794 curproxy->to_log |= LW_RSPHDR;
1795 }
1796 else {
1797 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 }
1802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 if (*(args[1]) == 0) {
1808 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 }
1813 curproxy->conn_retries = atol(args[1]);
1814 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001815 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1816 int pol = ACL_COND_NONE;
1817 struct acl_cond *cond;
1818
Willy Tarreaub099aca2008-10-12 17:26:37 +02001819 if (curproxy == &defproxy) {
1820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001823 }
1824
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001825 if (!strcmp(args[1], "if"))
1826 pol = ACL_COND_IF;
1827 else if (!strcmp(args[1], "unless"))
1828 pol = ACL_COND_UNLESS;
1829
1830 if (pol == ACL_COND_NONE) {
1831 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001835 }
1836
1837 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1838 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1839 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001842 }
Willy Tarreau88922352009-10-04 22:02:50 +02001843 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001844 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001845 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001846 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001847 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001848 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001849 else if (!strcmp(args[0], "redirect")) {
1850 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001851 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001852 struct redirect_rule *rule;
1853 int cur_arg;
1854 int type = REDIRECT_TYPE_NONE;
1855 int code = 302;
1856 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001857 char *cookie = NULL;
1858 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001859 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001860
Cyril Bonté99ed3272010-01-24 23:29:44 +01001861 if (curproxy == &defproxy) {
1862 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
1865 }
1866
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001867 cur_arg = 1;
1868 while (*(args[cur_arg])) {
1869 if (!strcmp(args[cur_arg], "location")) {
1870 if (!*args[cur_arg + 1]) {
1871 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1872 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001875 }
1876
1877 type = REDIRECT_TYPE_LOCATION;
1878 cur_arg++;
1879 destination = args[cur_arg];
1880 }
1881 else if (!strcmp(args[cur_arg], "prefix")) {
1882 if (!*args[cur_arg + 1]) {
1883 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1884 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001887 }
1888
1889 type = REDIRECT_TYPE_PREFIX;
1890 cur_arg++;
1891 destination = args[cur_arg];
1892 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001893 else if (!strcmp(args[cur_arg], "set-cookie")) {
1894 if (!*args[cur_arg + 1]) {
1895 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1896 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001899 }
1900
1901 cur_arg++;
1902 cookie = args[cur_arg];
1903 cookie_set = 1;
1904 }
1905 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1906 if (!*args[cur_arg + 1]) {
1907 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1908 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001911 }
1912
1913 cur_arg++;
1914 cookie = args[cur_arg];
1915 cookie_set = 0;
1916 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001917 else if (!strcmp(args[cur_arg],"code")) {
1918 if (!*args[cur_arg + 1]) {
1919 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001923 }
1924 cur_arg++;
1925 code = atol(args[cur_arg]);
1926 if (code < 301 || code > 303) {
1927 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1928 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001931 }
1932 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001933 else if (!strcmp(args[cur_arg],"drop-query")) {
1934 flags |= REDIRECT_FLAG_DROP_QS;
1935 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001936 else if (!strcmp(args[cur_arg],"append-slash")) {
1937 flags |= REDIRECT_FLAG_APPEND_SLASH;
1938 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001939 else if (!strcmp(args[cur_arg], "if")) {
1940 pol = ACL_COND_IF;
1941 cur_arg++;
1942 break;
1943 }
1944 else if (!strcmp(args[cur_arg], "unless")) {
1945 pol = ACL_COND_UNLESS;
1946 cur_arg++;
1947 break;
1948 }
1949 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001950 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 +02001951 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001954 }
1955 cur_arg++;
1956 }
1957
1958 if (type == REDIRECT_TYPE_NONE) {
1959 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001963 }
1964
Willy Tarreauf285f542010-01-03 20:03:03 +01001965 if (pol != ACL_COND_NONE &&
1966 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001967 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001968 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_ALERT | ERR_FATAL;
1970 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001971 }
1972
Willy Tarreauf285f542010-01-03 20:03:03 +01001973 if (cond) {
1974 cond->file = file;
1975 cond->line = linenum;
1976 curproxy->acl_requires |= cond->requires;
1977 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001978 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1979 rule->cond = cond;
1980 rule->rdr_str = strdup(destination);
1981 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001982 if (cookie) {
1983 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1984 * a clear consists in appending "; Max-Age=0" at the end.
1985 */
1986 rule->cookie_len = strlen(cookie);
1987 if (cookie_set)
1988 rule->cookie_str = strdup(cookie);
1989 else {
1990 rule->cookie_str = malloc(rule->cookie_len + 12);
1991 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1992 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1993 rule->cookie_len += 11;
1994 }
1995 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001996 rule->type = type;
1997 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001998 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001999 LIST_INIT(&rule->list);
2000 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002001 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002002 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002003 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002004 int pol = ACL_COND_NONE;
2005 struct acl_cond *cond;
2006 struct switching_rule *rule;
2007
Willy Tarreaub099aca2008-10-12 17:26:37 +02002008 if (curproxy == &defproxy) {
2009 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002012 }
2013
Willy Tarreau55ea7572007-06-17 19:56:27 +02002014 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002016
2017 if (*(args[1]) == 0) {
2018 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002021 }
2022
2023 if (!strcmp(args[2], "if"))
2024 pol = ACL_COND_IF;
2025 else if (!strcmp(args[2], "unless"))
2026 pol = ACL_COND_UNLESS;
2027
2028 if (pol == ACL_COND_NONE) {
2029 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002033 }
2034
2035 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002036 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002037 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002040 }
2041
Willy Tarreau88922352009-10-04 22:02:50 +02002042 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002043 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002044 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02002045 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02002046 struct acl *acl;
2047 const char *name;
2048
2049 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2050 name = acl ? acl->name : "(unknown)";
2051 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2052 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02002054 }
2055
Willy Tarreau55ea7572007-06-17 19:56:27 +02002056 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2057 rule->cond = cond;
2058 rule->be.name = strdup(args[1]);
2059 LIST_INIT(&rule->list);
2060 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2061 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002062 else if (!strcmp(args[0], "force-persist")) {
2063 int pol = ACL_COND_NONE;
2064 struct acl_cond *cond;
2065 struct force_persist_rule *rule;
2066
2067 if (curproxy == &defproxy) {
2068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2069 err_code |= ERR_ALERT | ERR_FATAL;
2070 goto out;
2071 }
2072
2073 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2074 err_code |= ERR_WARN;
2075
2076 if (!strcmp(args[1], "if"))
2077 pol = ACL_COND_IF;
2078 else if (!strcmp(args[1], "unless"))
2079 pol = ACL_COND_UNLESS;
2080
2081 if (pol == ACL_COND_NONE) {
2082 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2083 file, linenum, args[0]);
2084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
2086 }
2087
2088 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
2089 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2090 file, linenum);
2091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
2093 }
2094
2095 cond->file = file;
2096 cond->line = linenum;
2097 curproxy->acl_requires |= cond->requires;
2098 if (cond->requires & ACL_USE_RTR_ANY) {
2099 struct acl *acl;
2100 const char *name;
2101
2102 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2103 name = acl ? acl->name : "(unknown)";
2104 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2105 file, linenum, name);
2106 err_code |= ERR_WARN;
2107 }
2108
2109 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2110 rule->cond = cond;
2111 LIST_INIT(&rule->list);
2112 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2113 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002114 else if (!strcmp(args[0], "stick-table")) {
2115 int myidx = 1;
2116
2117 curproxy->table.type = (unsigned int)-1;
2118 while (*args[myidx]) {
2119 const char *err;
2120
2121 if (strcmp(args[myidx], "size") == 0) {
2122 myidx++;
2123 if (!*(args[myidx])) {
2124 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2125 file, linenum, args[myidx-1]);
2126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
2129 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2130 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2131 file, linenum, *err, args[myidx-1]);
2132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
2134 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002135 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002136 }
2137 else if (strcmp(args[myidx], "expire") == 0) {
2138 myidx++;
2139 if (!*(args[myidx])) {
2140 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2141 file, linenum, args[myidx-1]);
2142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
2144 }
2145 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2146 if (err) {
2147 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2148 file, linenum, *err, args[myidx-1]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002153 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002154 }
2155 else if (strcmp(args[myidx], "nopurge") == 0) {
2156 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002157 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002158 }
2159 else if (strcmp(args[myidx], "type") == 0) {
2160 myidx++;
2161 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2162 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2163 file, linenum, args[myidx]);
2164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
2166 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002167 /* myidx already points to next arg */
2168 }
2169 else {
2170 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2171 file, linenum, args[myidx]);
2172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002174 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002175 }
2176
2177 if (!curproxy->table.size) {
2178 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2179 file, linenum);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
2182 }
2183
2184 if (curproxy->table.type == (unsigned int)-1) {
2185 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2186 file, linenum);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190 }
2191 else if (!strcmp(args[0], "stick")) {
2192 int pol = ACL_COND_NONE;
2193 struct acl_cond *cond = NULL;
2194 struct sticking_rule *rule;
2195 struct pattern_expr *expr;
2196 int myidx = 0;
2197 const char *name = NULL;
2198 int flags;
2199
2200 if (curproxy == &defproxy) {
2201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205
2206 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2207 err_code |= ERR_WARN;
2208 goto out;
2209 }
2210
2211 myidx++;
2212 if ((strcmp(args[myidx], "store") == 0) ||
2213 (strcmp(args[myidx], "store-request") == 0)) {
2214 myidx++;
2215 flags = STK_IS_STORE;
2216 }
2217 else if (strcmp(args[myidx], "store-response") == 0) {
2218 myidx++;
2219 flags = STK_IS_STORE | STK_ON_RSP;
2220 }
2221 else if (strcmp(args[myidx], "match") == 0) {
2222 myidx++;
2223 flags = STK_IS_MATCH;
2224 }
2225 else if (strcmp(args[myidx], "on") == 0) {
2226 myidx++;
2227 flags = STK_IS_MATCH | STK_IS_STORE;
2228 }
2229 else {
2230 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
2233 }
2234
2235 if (*(args[myidx]) == 0) {
2236 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240
2241 expr = pattern_parse_expr(args, &myidx);
2242 if (!expr) {
2243 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
2248 if (flags & STK_ON_RSP) {
2249 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2250 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2251 file, linenum, args[0], expr->fetch->kw);
2252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
2254 }
2255 } else {
2256 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2257 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2258 file, linenum, args[0], expr->fetch->kw);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262 }
2263
2264 if (strcmp(args[myidx], "table") == 0) {
2265 myidx++;
2266 name = args[myidx++];
2267 }
2268
2269 if (*(args[myidx]) == 0)
2270 pol = ACL_COND_NONE;
2271 else if (strcmp(args[myidx], "if") == 0)
2272 pol = ACL_COND_IF;
2273 else if (strcmp(args[myidx], "unless") == 0)
2274 pol = ACL_COND_UNLESS;
2275 else {
2276 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2277 file, linenum, args[0], args[myidx]);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
2280 }
2281
2282 if (pol != ACL_COND_NONE) {
2283 myidx++;
2284 if ((cond = parse_acl_cond((const char **)args + myidx, &curproxy->acl, pol)) == NULL) {
2285 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2286 file, linenum, args[0]);
2287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
2289 }
2290
2291 cond->file = file;
2292 cond->line = linenum;
2293 curproxy->acl_requires |= cond->requires;
2294 if (cond->requires & ACL_USE_RTR_ANY) {
2295 struct acl *acl;
2296 const char *name;
2297
2298 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2299 name = acl ? acl->name : "(unknown)";
2300 Warning("parsing [%s:%d] : '%s' : acl '%s' involves some response-only criteria which will be ignored.\n",
2301 file, linenum, args[0], name);
2302 err_code |= ERR_WARN;
2303 }
2304 }
2305 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2306 rule->cond = cond;
2307 rule->expr = expr;
2308 rule->flags = flags;
2309 rule->table.name = name ? strdup(name) : NULL;
2310 LIST_INIT(&rule->list);
2311 if (flags & STK_ON_RSP)
2312 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2313 else
2314 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2321 curproxy->uri_auth = NULL; /* we must detach from the default config */
2322
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002323 if (!*args[1]) {
2324 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002325 } else if (!strcmp(args[1], "uri")) {
2326 if (*(args[2]) == 0) {
2327 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2331 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_ALERT | ERR_ABORT;
2333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 }
2335 } else if (!strcmp(args[1], "realm")) {
2336 if (*(args[2]) == 0) {
2337 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_ABORT;
2343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002345 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002346 unsigned interval;
2347
2348 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2349 if (err) {
2350 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2351 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002354 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 } else if (!strcmp(args[1], "auth")) {
2360 if (*(args[2]) == 0) {
2361 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2365 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_ABORT;
2367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369 } else if (!strcmp(args[1], "scope")) {
2370 if (*(args[2]) == 0) {
2371 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2375 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_ABORT;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379 } else if (!strcmp(args[1], "enable")) {
2380 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2381 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_ABORT;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002385 } else if (!strcmp(args[1], "hide-version")) {
2386 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_ABORT;
2389 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002390 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002391 } else if (!strcmp(args[1], "show-legends")) {
2392 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2393 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2394 err_code |= ERR_ALERT | ERR_ABORT;
2395 goto out;
2396 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002397 } else if (!strcmp(args[1], "show-node")) {
2398
2399 if (*args[2]) {
2400 int i;
2401 char c;
2402
2403 for (i=0; args[2][i]; i++) {
2404 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002405 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002406 break;
2407 }
2408
2409 if (!i || args[2][i]) {
2410 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2411 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2412 file, linenum, args[0], args[1]);
2413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
2415 }
2416 }
2417
2418 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2419 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2420 err_code |= ERR_ALERT | ERR_ABORT;
2421 goto out;
2422 }
2423 } else if (!strcmp(args[1], "show-desc")) {
2424 char *desc = NULL;
2425
2426 if (*args[2]) {
2427 int i, len=0;
2428 char *d;
2429
2430 for(i=2; *args[i]; i++)
2431 len += strlen(args[i])+1;
2432
2433 desc = d = (char *)calloc(1, len);
2434
2435 d += sprintf(d, "%s", args[2]);
2436 for(i=3; *args[i]; i++)
2437 d += sprintf(d, " %s", args[i]);
2438 }
2439
2440 if (!*args[2] && !global.desc)
2441 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2442 file, linenum, args[1]);
2443 else {
2444 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2445 free(desc);
2446 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2447 err_code |= ERR_ALERT | ERR_ABORT;
2448 goto out;
2449 }
2450 free(desc);
2451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002453stats_error_parsing:
2454 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2455 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
2459 }
2460 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002461 int optnum;
2462
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002463 if (*(args[1]) == '\0') {
2464 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002469
2470 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2471 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002472 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2473 err_code |= ERR_WARN;
2474 goto out;
2475 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002476
Willy Tarreau3842f002009-06-14 11:39:52 +02002477 curproxy->no_options &= ~cfg_opts[optnum].val;
2478 curproxy->options &= ~cfg_opts[optnum].val;
2479
2480 switch (kwm) {
2481 case KWM_STD:
2482 curproxy->options |= cfg_opts[optnum].val;
2483 break;
2484 case KWM_NO:
2485 curproxy->no_options |= cfg_opts[optnum].val;
2486 break;
2487 case KWM_DEF: /* already cleared */
2488 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002489 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002490
Willy Tarreau93893792009-07-23 13:19:11 +02002491 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002492 }
2493 }
2494
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002495 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2496 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002497 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2498 err_code |= ERR_WARN;
2499 goto out;
2500 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002501
Willy Tarreau3842f002009-06-14 11:39:52 +02002502 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2503 curproxy->options2 &= ~cfg_opts2[optnum].val;
2504
2505 switch (kwm) {
2506 case KWM_STD:
2507 curproxy->options2 |= cfg_opts2[optnum].val;
2508 break;
2509 case KWM_NO:
2510 curproxy->no_options2 |= cfg_opts2[optnum].val;
2511 break;
2512 case KWM_DEF: /* already cleared */
2513 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002514 }
Willy Tarreau93893792009-07-23 13:19:11 +02002515 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002516 }
2517 }
2518
Willy Tarreau3842f002009-06-14 11:39:52 +02002519 if (kwm != KWM_STD) {
2520 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002521 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002524 }
2525
Emeric Brun3a058f32009-06-30 18:26:00 +02002526 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002528 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002530 if (*(args[2]) != '\0') {
2531 if (!strcmp(args[2], "clf")) {
2532 curproxy->options2 |= PR_O2_CLFLOG;
2533 } else {
2534 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002537 }
2538 }
2539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 else if (!strcmp(args[1], "tcplog"))
2541 /* generate a detailed TCP log */
2542 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 else if (!strcmp(args[1], "tcpka")) {
2544 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002545 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002547
2548 if (curproxy->cap & PR_CAP_FE)
2549 curproxy->options |= PR_O_TCP_CLI_KA;
2550 if (curproxy->cap & PR_CAP_BE)
2551 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002554 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_WARN;
2556
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002558 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002559 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002560 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002561 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002562 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 if (!*args[2]) { /* no argument */
2564 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2565 curproxy->check_len = strlen(DEF_CHECK_REQ);
2566 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002567 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568 curproxy->check_req = (char *)malloc(reqlen);
2569 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2570 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2571 } else { /* more arguments : METHOD URI [HTTP_VER] */
2572 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2573 if (*args[4])
2574 reqlen += strlen(args[4]);
2575 else
2576 reqlen += strlen("HTTP/1.0");
2577
2578 curproxy->check_req = (char *)malloc(reqlen);
2579 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2580 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2581 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002582 }
2583 else if (!strcmp(args[1], "ssl-hello-chk")) {
2584 /* use SSLv3 CLIENT HELLO to check servers' health */
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;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002587
Willy Tarreaua534fea2008-08-03 12:19:50 +02002588 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002589 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002590 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002591 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002592 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Willy Tarreau23677902007-05-08 23:50:35 +02002594 else if (!strcmp(args[1], "smtpchk")) {
2595 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002596 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002597 curproxy->options &= ~PR_O_HTTP_CHK;
2598 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002599 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002600 curproxy->options |= PR_O_SMTP_CHK;
2601
2602 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2603 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2604 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2605 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2606 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2607 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2608 curproxy->check_req = (char *)malloc(reqlen);
2609 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2610 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2611 } else {
2612 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2613 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2614 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2615 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2616 }
2617 }
2618 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002619 else if (!strcmp(args[1], "mysql-check")) {
2620 /* use MYSQL request to check servers' health */
2621 free(curproxy->check_req);
2622 curproxy->options &= ~PR_O_HTTP_CHK;
2623 curproxy->options &= ~PR_O_SSL3_CHK;
2624 curproxy->options &= ~PR_O_SMTP_CHK;
2625 curproxy->options2 |= PR_O2_MYSQL_CHK;
2626 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002627 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002628 int cur_arg;
2629
2630 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2631 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002632 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002633
2634 curproxy->options |= PR_O_FWDFOR;
2635
2636 free(curproxy->fwdfor_hdr_name);
2637 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2638 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2639
2640 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2641 cur_arg = 2;
2642 while (*(args[cur_arg])) {
2643 if (!strcmp(args[cur_arg], "except")) {
2644 /* suboption except - needs additional argument for it */
2645 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2646 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2647 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002650 }
2651 /* flush useless bits */
2652 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002653 cur_arg += 2;
2654 } else if (!strcmp(args[cur_arg], "header")) {
2655 /* suboption header - needs additional argument for it */
2656 if (*(args[cur_arg+1]) == 0) {
2657 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2658 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002661 }
2662 free(curproxy->fwdfor_hdr_name);
2663 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2664 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2665 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002666 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002667 /* unknown suboption - catchall */
2668 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2669 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002672 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002673 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002674 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002675 else if (!strcmp(args[1], "originalto")) {
2676 int cur_arg;
2677
2678 /* insert x-original-to field, but not for the IP address listed as an except.
2679 * set default options (ie: bitfield, header name, etc)
2680 */
2681
2682 curproxy->options |= PR_O_ORGTO;
2683
2684 free(curproxy->orgto_hdr_name);
2685 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2686 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2687
2688 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2689 cur_arg = 2;
2690 while (*(args[cur_arg])) {
2691 if (!strcmp(args[cur_arg], "except")) {
2692 /* suboption except - needs additional argument for it */
2693 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2694 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2695 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002698 }
2699 /* flush useless bits */
2700 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2701 cur_arg += 2;
2702 } else if (!strcmp(args[cur_arg], "header")) {
2703 /* suboption header - needs additional argument for it */
2704 if (*(args[cur_arg+1]) == 0) {
2705 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2706 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002709 }
2710 free(curproxy->orgto_hdr_name);
2711 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2712 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2713 cur_arg += 2;
2714 } else {
2715 /* unknown suboption - catchall */
2716 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2717 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002720 }
2721 } /* end while loop */
2722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 else {
2724 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 }
Willy Tarreau93893792009-07-23 13:19:11 +02002728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002730 else if (!strcmp(args[0], "default_backend")) {
2731 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002733
2734 if (*(args[1]) == 0) {
2735 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002738 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002739 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002740 curproxy->defbe.name = strdup(args[1]);
2741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002746 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 /* enable reconnections to dispatch */
2750 curproxy->options |= PR_O_REDISP;
2751 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002752 else if (!strcmp(args[0], "http-check")) {
2753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002755
2756 if (strcmp(args[1], "disable-on-404") == 0) {
2757 /* enable a graceful server shutdown on an HTTP 404 response */
2758 curproxy->options |= PR_O_DISABLE404;
2759 }
2760 else {
2761 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002764 }
2765 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002766 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002767 if (curproxy == &defproxy) {
2768 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002771 }
2772
Willy Tarreaub80c2302007-11-30 20:51:32 +01002773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002775
2776 if (strcmp(args[1], "fail") == 0) {
2777 /* add a condition to fail monitor requests */
2778 int pol = ACL_COND_NONE;
2779 struct acl_cond *cond;
2780
2781 if (!strcmp(args[2], "if"))
2782 pol = ACL_COND_IF;
2783 else if (!strcmp(args[2], "unless"))
2784 pol = ACL_COND_UNLESS;
2785
2786 if (pol == ACL_COND_NONE) {
2787 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2788 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002791 }
2792
2793 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2794 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2795 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002798 }
Willy Tarreau88922352009-10-04 22:02:50 +02002799 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002800 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002801 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002802 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2803 }
2804 else {
2805 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002808 }
2809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810#ifdef TPROXY
2811 else if (!strcmp(args[0], "transparent")) {
2812 /* enable transparent proxy connections */
2813 curproxy->options |= PR_O_TRANSP;
2814 }
2815#endif
2816 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002817 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002818 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002819
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 if (*(args[1]) == 0) {
2821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 }
2825 curproxy->maxconn = atol(args[1]);
2826 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002827 else if (!strcmp(args[0], "backlog")) { /* backlog */
2828 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002830
2831 if (*(args[1]) == 0) {
2832 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002835 }
2836 curproxy->backlog = atol(args[1]);
2837 }
Willy Tarreau86034312006-12-29 00:10:33 +01002838 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002841
Willy Tarreau86034312006-12-29 00:10:33 +01002842 if (*(args[1]) == 0) {
2843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002846 }
2847 curproxy->fullconn = atol(args[1]);
2848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2850 if (*(args[1]) == 0) {
2851 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002855 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2856 if (err) {
2857 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2858 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002861 }
2862 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2865 if (curproxy == &defproxy) {
2866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002870 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002872
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 if (strchr(args[1], ':') == NULL) {
2874 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878 curproxy->dispatch_addr = *str2sa(args[1]);
2879 }
2880 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002883
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002884 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002885 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2886 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002891 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2892 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2893 err_code |= ERR_WARN;
2894
2895 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2896 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2897 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2898 }
2899 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2900 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2901 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2902 }
2903 else {
2904 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002909 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002911 char *rport, *raddr;
2912 short realport = 0;
2913 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002915 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922
2923 if (!*args[2]) {
2924 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002929
2930 err = invalid_char(args[1]);
2931 if (err) {
2932 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2933 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002936 }
2937
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2939 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_ABORT;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
2943
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002944 if (!defsrv) {
2945 /* the servers are linked backwards first */
2946 newsrv->next = curproxy->srv;
2947 curproxy->srv = newsrv;
2948 newsrv->proxy = curproxy;
2949 newsrv->conf.file = file;
2950 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002952 LIST_INIT(&newsrv->pendconns);
2953 do_check = 0;
2954 newsrv->state = SRV_RUNNING; /* early server setup */
2955 newsrv->last_change = now.tv_sec;
2956 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002957
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002958 /* several ways to check the port component :
2959 * - IP => port=+0, relative
2960 * - IP: => port=+0, relative
2961 * - IP:N => port=N, absolute
2962 * - IP:+N => port=+N, relative
2963 * - IP:-N => port=-N, relative
2964 */
2965 raddr = strdup(args[2]);
2966 rport = strchr(raddr, ':');
2967 if (rport) {
2968 *rport++ = 0;
2969 realport = atol(rport);
2970 if (!isdigit((unsigned char)*rport))
2971 newsrv->state |= SRV_MAPPORTS;
2972 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002974
2975 newsrv->addr = *str2sa(raddr);
2976 newsrv->addr.sin_port = htons(realport);
2977 free(raddr);
2978
2979 newsrv->check_port = curproxy->defsrv.check_port;
2980 newsrv->inter = curproxy->defsrv.inter;
2981 newsrv->fastinter = curproxy->defsrv.fastinter;
2982 newsrv->downinter = curproxy->defsrv.downinter;
2983 newsrv->rise = curproxy->defsrv.rise;
2984 newsrv->fall = curproxy->defsrv.fall;
2985 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2986 newsrv->minconn = curproxy->defsrv.minconn;
2987 newsrv->maxconn = curproxy->defsrv.maxconn;
2988 newsrv->slowstart = curproxy->defsrv.slowstart;
2989 newsrv->onerror = curproxy->defsrv.onerror;
2990 newsrv->consecutive_errors_limit
2991 = curproxy->defsrv.consecutive_errors_limit;
2992 newsrv->uweight = newsrv->iweight
2993 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002995 newsrv->curfd = -1; /* no health-check in progress */
2996 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002998 cur_arg = 3;
2999 } else {
3000 newsrv = &curproxy->defsrv;
3001 cur_arg = 1;
3002 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003003
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003005 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003006 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003007
3008 if (!*args[cur_arg + 1]) {
3009 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3010 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003013 }
3014
3015 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003016 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003017
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003018 if (newsrv->puid <= 0) {
3019 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003020 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003023 }
3024
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003025 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3026 if (node) {
3027 struct server *target = container_of(node, struct server, conf.id);
3028 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3029 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003034 cur_arg += 2;
3035 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003036 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 newsrv->cookie = strdup(args[cur_arg + 1]);
3038 newsrv->cklen = strlen(args[cur_arg + 1]);
3039 cur_arg += 2;
3040 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003041 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003042 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3043 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3044 cur_arg += 2;
3045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003047 if (!*args[cur_arg + 1]) {
3048 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3049 file, linenum, args[cur_arg]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003055 if (newsrv->rise <= 0) {
3056 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3057 file, linenum, args[cur_arg]);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060 }
3061
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 newsrv->health = newsrv->rise;
3063 cur_arg += 2;
3064 }
3065 else if (!strcmp(args[cur_arg], "fall")) {
3066 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003067
3068 if (!*args[cur_arg + 1]) {
3069 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3070 file, linenum, args[cur_arg]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
3075 if (newsrv->fall <= 0) {
3076 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3077 file, linenum, args[cur_arg]);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
3080 }
3081
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 cur_arg += 2;
3083 }
3084 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003085 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3086 if (err) {
3087 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3088 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003091 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003092 if (val <= 0) {
3093 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3094 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003097 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003098 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 cur_arg += 2;
3100 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003101 else if (!strcmp(args[cur_arg], "fastinter")) {
3102 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3103 if (err) {
3104 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3105 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003108 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003109 if (val <= 0) {
3110 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3111 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_FATAL;
3113 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003114 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003115 newsrv->fastinter = val;
3116 cur_arg += 2;
3117 }
3118 else if (!strcmp(args[cur_arg], "downinter")) {
3119 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3120 if (err) {
3121 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3122 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003125 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003126 if (val <= 0) {
3127 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3128 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003131 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003132 newsrv->downinter = val;
3133 cur_arg += 2;
3134 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003135 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003136 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003137 cur_arg += 2;
3138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 else if (!strcmp(args[cur_arg], "port")) {
3140 newsrv->check_port = atol(args[cur_arg + 1]);
3141 cur_arg += 2;
3142 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003143 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 newsrv->state |= SRV_BACKUP;
3145 cur_arg ++;
3146 }
3147 else if (!strcmp(args[cur_arg], "weight")) {
3148 int w;
3149 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003150 if (w < 0 || w > 256) {
3151 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003156 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 cur_arg += 2;
3158 }
3159 else if (!strcmp(args[cur_arg], "minconn")) {
3160 newsrv->minconn = atol(args[cur_arg + 1]);
3161 cur_arg += 2;
3162 }
3163 else if (!strcmp(args[cur_arg], "maxconn")) {
3164 newsrv->maxconn = atol(args[cur_arg + 1]);
3165 cur_arg += 2;
3166 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003167 else if (!strcmp(args[cur_arg], "maxqueue")) {
3168 newsrv->maxqueue = atol(args[cur_arg + 1]);
3169 cur_arg += 2;
3170 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003171 else if (!strcmp(args[cur_arg], "slowstart")) {
3172 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003173 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003174 if (err) {
3175 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3176 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003179 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003180 if (val <= 0) {
3181 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3182 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003185 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003186 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003187 cur_arg += 2;
3188 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003189 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003190
3191 if (!*args[cur_arg + 1]) {
3192 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3193 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003196 }
3197
3198 newsrv->trackit = strdup(args[cur_arg + 1]);
3199
3200 cur_arg += 2;
3201 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003202 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 global.maxsock++;
3204 do_check = 1;
3205 cur_arg += 1;
3206 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003207 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003208 if (!strcmp(args[cur_arg + 1], "none"))
3209 newsrv->observe = HANA_OBS_NONE;
3210 else if (!strcmp(args[cur_arg + 1], "layer4"))
3211 newsrv->observe = HANA_OBS_LAYER4;
3212 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3213 if (curproxy->mode != PR_MODE_HTTP) {
3214 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3215 file, linenum, args[cur_arg + 1]);
3216 err_code |= ERR_ALERT;
3217 }
3218 newsrv->observe = HANA_OBS_LAYER7;
3219 }
3220 else {
3221 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3222 "'l4events', 'http-responses' but get '%s'\n",
3223 file, linenum, args[cur_arg], args[cur_arg + 1]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227
3228 cur_arg += 2;
3229 }
3230 else if (!strcmp(args[cur_arg], "on-error")) {
3231 if (!strcmp(args[cur_arg + 1], "fastinter"))
3232 newsrv->onerror = HANA_ONERR_FASTINTER;
3233 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3234 newsrv->onerror = HANA_ONERR_FAILCHK;
3235 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3236 newsrv->onerror = HANA_ONERR_SUDDTH;
3237 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3238 newsrv->onerror = HANA_ONERR_MARKDWN;
3239 else {
3240 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3241 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3242 file, linenum, args[cur_arg], args[cur_arg + 1]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
3246
3247 cur_arg += 2;
3248 }
3249 else if (!strcmp(args[cur_arg], "error-limit")) {
3250 if (!*args[cur_arg + 1]) {
3251 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3252 file, linenum, args[cur_arg]);
3253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
3255 }
3256
3257 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3258
3259 if (newsrv->consecutive_errors_limit <= 0) {
3260 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3261 file, linenum, args[cur_arg]);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003266 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003267 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003269#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003270 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003271 file, linenum, "source", "usesrc");
3272#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003273 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003275#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003280 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3281
3282 if (port_low != port_high) {
3283 int i;
3284 if (port_low <= 0 || port_low > 65535 ||
3285 port_high <= 0 || port_high > 65535 ||
3286 port_low > port_high) {
3287 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3288 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003291 }
3292 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3293 for (i = 0; i < newsrv->sport_range->size; i++)
3294 newsrv->sport_range->ports[i] = port_low + i;
3295 }
3296
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003298 while (*(args[cur_arg])) {
3299 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003300#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3301#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003302 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3303 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3304 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003307 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003308#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003309 if (!*args[cur_arg + 1]) {
3310 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3311 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003314 }
3315 if (!strcmp(args[cur_arg + 1], "client")) {
3316 newsrv->state |= SRV_TPROXY_CLI;
3317 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3318 newsrv->state |= SRV_TPROXY_CIP;
3319 } else {
3320 newsrv->state |= SRV_TPROXY_ADDR;
3321 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3322 }
3323 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003324#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003325 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003326#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003327 cur_arg += 2;
3328 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003329#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003330 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003331 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003334#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3335 } /* "usesrc" */
3336
3337 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3338#ifdef SO_BINDTODEVICE
3339 if (!*args[cur_arg + 1]) {
3340 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003344 }
3345 if (newsrv->iface_name)
3346 free(newsrv->iface_name);
3347
3348 newsrv->iface_name = strdup(args[cur_arg + 1]);
3349 newsrv->iface_len = strlen(newsrv->iface_name);
3350 global.last_checks |= LSTCHK_NETADM;
3351#else
3352 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3353 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003356#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003357 cur_arg += 2;
3358 continue;
3359 }
3360 /* this keyword in not an option of "source" */
3361 break;
3362 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003364 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003365 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3366 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003371 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003372 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 +01003373 file, linenum, newsrv->id);
3374 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003375 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 +01003376 file, linenum);
3377
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 }
3381 }
3382
3383 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003384 if (newsrv->trackit) {
3385 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003389 }
3390
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003391 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3392 newsrv->check_port = newsrv->check_addr.sin_port;
3393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3395 newsrv->check_port = realport; /* by default */
3396 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003397 /* not yet valid, because no port was set on
3398 * the server either. We'll check if we have
3399 * a known port on the first listener.
3400 */
3401 struct listener *l;
3402 l = curproxy->listen;
3403 if (l) {
3404 int port;
3405 port = (l->addr.ss_family == AF_INET6)
3406 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3407 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3408 newsrv->check_port = port;
3409 }
3410 }
3411 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3413 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003417
3418 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 newsrv->state |= SRV_CHECKED;
3420 }
3421
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003422 if (!defsrv) {
3423 if (newsrv->state & SRV_BACKUP)
3424 curproxy->srv_bck++;
3425 else
3426 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003427
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003428 newsrv->prev_state = newsrv->state;
3429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 }
3431 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003432 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 int facility;
3434
3435 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3436 curproxy->logfac1 = global.logfac1;
3437 curproxy->logsrv1 = global.logsrv1;
3438 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003439 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 curproxy->logfac2 = global.logfac2;
3441 curproxy->logsrv2 = global.logsrv2;
3442 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003443 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 }
3445 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003446 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447
3448 facility = get_log_facility(args[2]);
3449 if (facility < 0) {
3450 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3451 exit(1);
3452 }
3453
3454 level = 7; /* max syslog level = debug */
3455 if (*(args[3])) {
3456 level = get_log_level(args[3]);
3457 if (level < 0) {
3458 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3459 exit(1);
3460 }
3461 }
3462
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003463 minlvl = 0; /* limit syslog level to this level (emerg) */
3464 if (*(args[4])) {
3465 minlvl = get_log_level(args[4]);
3466 if (level < 0) {
3467 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3468 exit(1);
3469 }
3470 }
3471
Robert Tsai81ae1952007-12-05 10:47:29 +01003472 if (args[1][0] == '/') {
3473 logsrv.u.addr.sa_family = AF_UNIX;
3474 logsrv.u.un = *str2sun(args[1]);
3475 } else {
3476 logsrv.u.addr.sa_family = AF_INET;
3477 logsrv.u.in = *str2sa(args[1]);
3478 if (!logsrv.u.in.sin_port) {
3479 logsrv.u.in.sin_port =
3480 htons(SYSLOG_PORT);
3481 }
3482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483
3484 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003485 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 curproxy->logfac1 = facility;
3487 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003488 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 }
3490 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003491 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 curproxy->logfac2 = facility;
3493 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003494 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495 }
3496 else {
3497 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 }
3501 }
3502 else {
3503 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3504 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_ALERT | ERR_FATAL;
3506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 }
3508 }
3509 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003510 int cur_arg;
3511
Willy Tarreau977b8e42006-12-29 14:19:17 +01003512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003514
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003516 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3517 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003521
3522 /* we must first clear any optional default setting */
3523 curproxy->options &= ~PR_O_TPXY_MASK;
3524 free(curproxy->iface_name);
3525 curproxy->iface_name = NULL;
3526 curproxy->iface_len = 0;
3527
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 curproxy->source_addr = *str2sa(args[1]);
3529 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003530
3531 cur_arg = 2;
3532 while (*(args[cur_arg])) {
3533 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003534#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3535#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003536 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3537 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3538 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003541 }
3542#endif
3543 if (!*args[cur_arg + 1]) {
3544 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3545 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003548 }
3549
3550 if (!strcmp(args[cur_arg + 1], "client")) {
3551 curproxy->options |= PR_O_TPXY_CLI;
3552 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3553 curproxy->options |= PR_O_TPXY_CIP;
3554 } else {
3555 curproxy->options |= PR_O_TPXY_ADDR;
3556 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3557 }
3558 global.last_checks |= LSTCHK_NETADM;
3559#if !defined(CONFIG_HAP_LINUX_TPROXY)
3560 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003561#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003562#else /* no TPROXY support */
3563 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003564 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003567#endif
3568 cur_arg += 2;
3569 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003570 }
3571
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003572 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3573#ifdef SO_BINDTODEVICE
3574 if (!*args[cur_arg + 1]) {
3575 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003579 }
3580 if (curproxy->iface_name)
3581 free(curproxy->iface_name);
3582
3583 curproxy->iface_name = strdup(args[cur_arg + 1]);
3584 curproxy->iface_len = strlen(curproxy->iface_name);
3585 global.last_checks |= LSTCHK_NETADM;
3586#else
3587 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3588 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003591#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003592 cur_arg += 2;
3593 continue;
3594 }
3595 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3596 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003601 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3602 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3603 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3608 regex_t *preg;
3609 if (curproxy == &defproxy) {
3610 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003614 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003616
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 if (*(args[1]) == 0 || *(args[2]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623
3624 preg = calloc(1, sizeof(regex_t));
3625 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3626 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
3630
3631 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3632 if (err) {
3633 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3634 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003637 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
3639 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3640 regex_t *preg;
3641 if (curproxy == &defproxy) {
3642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003646 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003648
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 if (*(args[1]) == 0) {
3650 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 }
3654
3655 preg = calloc(1, sizeof(regex_t));
3656 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3657 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 }
3661
3662 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003663 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 }
3665 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3666 regex_t *preg;
3667 if (curproxy == &defproxy) {
3668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003672 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003674
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 if (*(args[1]) == 0) {
3676 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 }
3680
3681 preg = calloc(1, sizeof(regex_t));
3682 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3683 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 }
3687
3688 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003689 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 }
3691 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3692 regex_t *preg;
3693 if (curproxy == &defproxy) {
3694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003698 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003700
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 if (*(args[1]) == 0) {
3702 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706
3707 preg = calloc(1, sizeof(regex_t));
3708 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3709 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
3713
3714 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003715 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
3717 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3718 regex_t *preg;
3719 if (curproxy == &defproxy) {
3720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003724 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003726
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727 if (*(args[1]) == 0) {
3728 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 }
3732
3733 preg = calloc(1, sizeof(regex_t));
3734 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3735 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 }
3739
3740 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003741 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003743 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3744 regex_t *preg;
3745 if (curproxy == &defproxy) {
3746 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003749 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752
Willy Tarreaub8750a82006-09-03 09:56:00 +02003753 if (*(args[1]) == 0) {
3754 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003757 }
3758
3759 preg = calloc(1, sizeof(regex_t));
3760 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3761 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003764 }
3765
3766 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003767 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003768 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003769 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3770 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003772 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003775 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003778
Willy Tarreau977b8e42006-12-29 14:19:17 +01003779 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003780 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003784 }
3785
3786 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003788 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003791 }
3792
3793 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003794 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003795 }
3796 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3797 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003803 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003805
Willy Tarreau977b8e42006-12-29 14:19:17 +01003806 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003807 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3808 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003811 }
3812
3813 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003814 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003815 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003818 }
3819
3820 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003821 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3824 regex_t *preg;
3825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003830 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003832
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 if (*(args[1]) == 0 || *(args[2]) == 0) {
3834 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
3839
3840 preg = calloc(1, sizeof(regex_t));
3841 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3842 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 }
3846
3847 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3848 if (err) {
3849 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3850 file, linenum, *err);
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 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003854 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 }
3856 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3857 regex_t *preg;
3858 if (curproxy == &defproxy) {
3859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003865
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 if (*(args[1]) == 0) {
3867 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 }
3871
3872 preg = calloc(1, sizeof(regex_t));
3873 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3874 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
3878
3879 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003880 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
3882 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3883 regex_t *preg;
3884 if (curproxy == &defproxy) {
3885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 if (*(args[1]) == 0) {
3893 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
3897
3898 preg = calloc(1, sizeof(regex_t));
3899 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3900 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 }
3904
3905 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003906 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
3908 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3909 regex_t *preg;
3910 if (curproxy == &defproxy) {
3911 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003917
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918 if (*(args[1]) == 0) {
3919 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922 }
3923
3924 preg = calloc(1, sizeof(regex_t));
3925 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3926 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 }
3930
3931 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003932 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
3934 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3935 regex_t *preg;
3936 if (curproxy == &defproxy) {
3937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003941 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 if (*(args[1]) == 0) {
3945 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949
3950 preg = calloc(1, sizeof(regex_t));
3951 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3952 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 }
3956
3957 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003958 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003960 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3961 regex_t *preg;
3962 if (curproxy == &defproxy) {
3963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003966 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003967 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003969
Willy Tarreaub8750a82006-09-03 09:56:00 +02003970 if (*(args[1]) == 0) {
3971 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003974 }
3975
3976 preg = calloc(1, sizeof(regex_t));
3977 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3978 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003981 }
3982
3983 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003984 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003987 struct wordlist *wl;
3988
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 if (curproxy == &defproxy) {
3990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003994 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 if (*(args[1]) == 0) {
3998 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004002
4003 wl = calloc(1, sizeof(*wl));
4004 wl->s = strdup(args[1]);
4005 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004006 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
4008 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
4009 regex_t *preg;
Cyril Bonté99ed3272010-01-24 23:29:44 +01004010 if (curproxy == &defproxy) {
4011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015
4016 if (*(args[1]) == 0 || *(args[2]) == 0) {
4017 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004022 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004024
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 preg = calloc(1, sizeof(regex_t));
4026 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4027 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 }
4031
4032 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4033 if (err) {
4034 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4035 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 }
Willy Tarreau61d18892009-03-31 10:49:21 +02004039 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 }
4041 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
4042 regex_t *preg;
4043 if (curproxy == &defproxy) {
4044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004048 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004050
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 if (*(args[1]) == 0) {
4052 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055 }
4056
4057 preg = calloc(1, sizeof(regex_t));
4058 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4059 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 }
4063
4064 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4065 if (err) {
4066 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4067 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_ALERT | ERR_FATAL;
4069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 }
4071 }
4072 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
4073 regex_t *preg;
4074 if (curproxy == &defproxy) {
4075 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004079 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004081
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 if (*(args[1]) == 0) {
4083 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
4087
4088 preg = calloc(1, sizeof(regex_t));
4089 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4090 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 }
4094
4095 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4096 if (err) {
4097 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4098 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101 }
4102 }
4103 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
4104 regex_t *preg;
4105 if (curproxy == &defproxy) {
4106 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004110 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112
4113 if (*(args[1]) == 0 || *(args[2]) == 0) {
4114 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4115 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118 }
4119
4120 preg = calloc(1, sizeof(regex_t));
4121 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4122 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 }
4126
4127 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4128 if (err) {
4129 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4130 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 }
4134 }
4135 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
4136 regex_t *preg;
4137 if (curproxy == &defproxy) {
4138 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004142 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004143 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004144
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 if (*(args[1]) == 0) {
4146 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 }
4150
4151 preg = calloc(1, sizeof(regex_t));
4152 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4153 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
4157
4158 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4159 if (err) {
4160 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4161 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 }
4165 }
4166 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
4167 regex_t *preg;
4168 if (curproxy == &defproxy) {
4169 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004173 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004175
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 if (*(args[1]) == 0) {
4177 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 }
4181
4182 preg = calloc(1, sizeof(regex_t));
4183 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4184 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
4188
4189 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4190 if (err) {
4191 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4192 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 }
4196 }
4197 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004198 struct wordlist *wl;
4199
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 if (curproxy == &defproxy) {
4201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004205 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 if (*(args[1]) == 0) {
4209 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 }
4213
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004214 wl = calloc(1, sizeof(*wl));
4215 wl->s = strdup(args[1]);
4216 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217 }
4218 else if (!strcmp(args[0], "errorloc") ||
4219 !strcmp(args[0], "errorloc302") ||
4220 !strcmp(args[0], "errorloc303")) { /* error location */
4221 int errnum, errlen;
4222 char *err;
4223
Willy Tarreau977b8e42006-12-29 14:19:17 +01004224 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004226
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004228 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 }
4232
4233 errnum = atol(args[1]);
4234 if (!strcmp(args[0], "errorloc303")) {
4235 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4236 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4237 } else {
4238 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4239 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4240 }
4241
Willy Tarreau0f772532006-12-23 20:51:41 +01004242 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4243 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004244 chunk_destroy(&curproxy->errmsg[rc]);
4245 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004246 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004249
4250 if (rc >= HTTP_ERR_SIZE) {
4251 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4252 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 free(err);
4254 }
4255 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004256 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4257 int errnum, errlen, fd;
4258 char *err;
4259 struct stat stat;
4260
4261 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004263
4264 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004265 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004268 }
4269
4270 fd = open(args[2], O_RDONLY);
4271 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4272 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4273 file, linenum, args[2], args[1]);
4274 if (fd >= 0)
4275 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004278 }
4279
Willy Tarreau27a674e2009-08-17 07:23:33 +02004280 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004281 errlen = stat.st_size;
4282 } else {
4283 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004284 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004285 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004286 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004287 }
4288
4289 err = malloc(errlen); /* malloc() must succeed during parsing */
4290 errnum = read(fd, err, errlen);
4291 if (errnum != errlen) {
4292 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4293 file, linenum, args[2], args[1]);
4294 close(fd);
4295 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004298 }
4299 close(fd);
4300
4301 errnum = atol(args[1]);
4302 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4303 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004304 chunk_destroy(&curproxy->errmsg[rc]);
4305 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004306 break;
4307 }
4308 }
4309
4310 if (rc >= HTTP_ERR_SIZE) {
4311 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4312 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004314 free(err);
4315 }
4316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004318 struct cfg_kw_list *kwl;
4319 int index;
4320
4321 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4322 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4323 if (kwl->kw[index].section != CFG_LISTEN)
4324 continue;
4325 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4326 /* prepare error message just in case */
4327 snprintf(trash, sizeof(trash),
4328 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004329 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4330 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004331 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004334 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004335 else if (rc > 0) {
4336 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_WARN;
4338 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004339 }
Willy Tarreau93893792009-07-23 13:19:11 +02004340 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004341 }
4342 }
4343 }
4344
Willy Tarreau6daf3432008-01-22 16:44:08 +01004345 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004348 }
Willy Tarreau93893792009-07-23 13:19:11 +02004349 out:
4350 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351}
4352
4353
4354/*
4355 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004356 * Returns the error code, 0 if OK, or any combination of :
4357 * - ERR_ABORT: must abort ASAP
4358 * - ERR_FATAL: we can continue parsing but not start the service
4359 * - ERR_WARN: a warning has been emitted
4360 * - ERR_ALERT: an alert has been emitted
4361 * Only the two first ones can stop processing, the two others are just
4362 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004364int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004366 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 FILE *f;
4368 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004369 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004370 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 if ((f=fopen(file,"r")) == NULL)
4373 return -1;
4374
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004375 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004376 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004377 char *end;
4378 char *args[MAX_LINE_ARGS + 1];
4379 char *line = thisline;
4380
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 linenum++;
4382
4383 end = line + strlen(line);
4384
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004385 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4386 /* Check if we reached the limit and the last char is not \n.
4387 * Watch out for the last line without the terminating '\n'!
4388 */
4389 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004390 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004392 }
4393
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004395 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 line++;
4397
4398 arg = 0;
4399 args[arg] = line;
4400
4401 while (*line && arg < MAX_LINE_ARGS) {
4402 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4403 * C equivalent value. Other combinations left unchanged (eg: \1).
4404 */
4405 if (*line == '\\') {
4406 int skip = 0;
4407 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4408 *line = line[1];
4409 skip = 1;
4410 }
4411 else if (line[1] == 'r') {
4412 *line = '\r';
4413 skip = 1;
4414 }
4415 else if (line[1] == 'n') {
4416 *line = '\n';
4417 skip = 1;
4418 }
4419 else if (line[1] == 't') {
4420 *line = '\t';
4421 skip = 1;
4422 }
4423 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004424 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 unsigned char hex1, hex2;
4426 hex1 = toupper(line[2]) - '0';
4427 hex2 = toupper(line[3]) - '0';
4428 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4429 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4430 *line = (hex1<<4) + hex2;
4431 skip = 3;
4432 }
4433 else {
4434 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 }
4437 }
4438 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004439 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 end -= skip;
4441 }
4442 line++;
4443 }
4444 else if (*line == '#' || *line == '\n' || *line == '\r') {
4445 /* end of string, end of loop */
4446 *line = 0;
4447 break;
4448 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004449 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004451 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004452 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 line++;
4454 args[++arg] = line;
4455 }
4456 else {
4457 line++;
4458 }
4459 }
4460
4461 /* empty line */
4462 if (!**args)
4463 continue;
4464
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004465 if (*line) {
4466 /* we had to stop due to too many args.
4467 * Let's terminate the string, print the offending part then cut the
4468 * last arg.
4469 */
4470 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4471 line++;
4472 *line = '\0';
4473
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004474 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004475 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 args[arg] = line;
4478 }
4479
Willy Tarreau540abe42007-05-02 20:50:16 +02004480 /* zero out remaining args and ensure that at least one entry
4481 * is zeroed out.
4482 */
4483 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 args[arg] = line;
4485 }
4486
Willy Tarreau3842f002009-06-14 11:39:52 +02004487 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004488 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004489 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004490 for (arg=0; *args[arg+1]; arg++)
4491 args[arg] = args[arg+1]; // shift args after inversion
4492 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004493 else if (!strcmp(args[0], "default")) {
4494 kwm = KWM_DEF;
4495 for (arg=0; *args[arg+1]; arg++)
4496 args[arg] = args[arg+1]; // shift args after inversion
4497 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004498
Willy Tarreau3842f002009-06-14 11:39:52 +02004499 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4500 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004501 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004502 }
4503
Willy Tarreau977b8e42006-12-29 14:19:17 +01004504 if (!strcmp(args[0], "listen") ||
4505 !strcmp(args[0], "frontend") ||
4506 !strcmp(args[0], "backend") ||
4507 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004508 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004510 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004511 cursection = strdup(args[0]);
4512 }
4513 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004515 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004516 cursection = strdup(args[0]);
4517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 /* else it's a section keyword */
4519
4520 switch (confsect) {
4521 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004522 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 break;
4524 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004525 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 break;
4527 default:
4528 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004531
4532 if (err_code & ERR_ABORT)
4533 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004535 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004536 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004538 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004539}
4540
Willy Tarreaubb925012009-07-23 13:36:36 +02004541/*
4542 * Returns the error code, 0 if OK, or any combination of :
4543 * - ERR_ABORT: must abort ASAP
4544 * - ERR_FATAL: we can continue parsing but not start the service
4545 * - ERR_WARN: a warning has been emitted
4546 * - ERR_ALERT: an alert has been emitted
4547 * Only the two first ones can stop processing, the two others are just
4548 * indicators.
4549 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004550int check_config_validity()
4551{
4552 int cfgerr = 0;
4553 struct proxy *curproxy = NULL;
4554 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004555 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004556 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557
4558 /*
4559 * Now, check for the integrity of all that we have collected.
4560 */
4561
4562 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004563 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004565 /* first, we will invert the proxy list order */
4566 curproxy = NULL;
4567 while (proxy) {
4568 struct proxy *next;
4569
4570 next = proxy->next;
4571 proxy->next = curproxy;
4572 curproxy = proxy;
4573 if (!next)
4574 break;
4575 proxy = next;
4576 }
4577
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004579 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583
4584 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004585 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004586 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004587 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004588 unsigned int next_id;
4589
4590 if (!curproxy->uuid) {
4591 /* proxy ID not set, use automatic numbering with first
4592 * spare entry starting with next_pxid.
4593 */
4594 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4595 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4596 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4597 next_pxid++;
4598 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004599
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004601 /* ensure we don't keep listeners uselessly bound */
4602 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 curproxy = curproxy->next;
4604 continue;
4605 }
4606
Willy Tarreauff01a212009-03-15 13:46:16 +01004607 switch (curproxy->mode) {
4608 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004609 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004610 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004611 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004613 cfgerr++;
4614 }
4615
4616 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004617 Warning("config : servers will be ignored for %s '%s'.\n",
4618 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004619 break;
4620
4621 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004622 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004623 break;
4624
4625 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004626 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004627 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004628 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4629 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004630 cfgerr++;
4631 }
4632 break;
4633 }
4634
4635 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004636 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4637 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 cfgerr++;
4639 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004640
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004641 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004642 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004643 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004644 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4645 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004646 cfgerr++;
4647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004649 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004650 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4651 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004652 cfgerr++;
4653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004655 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004656 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4657 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004658 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004659 }
4660 }
4661 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4662 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4663 /* If no LB algo is set in a backend, and we're not in
4664 * transparent mode, dispatch mode nor proxy mode, we
4665 * want to use balance roundrobin by default.
4666 */
4667 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4668 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
4670 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004671
Willy Tarreau82936582007-11-30 15:20:09 +01004672 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4673 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004674 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4675 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004676 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004677 }
4678
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004679 /* if a default backend was specified, let's find it */
4680 if (curproxy->defbe.name) {
4681 struct proxy *target;
4682
Alex Williams96532db2009-11-01 21:27:13 -05004683 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004684 if (!target) {
4685 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4686 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004687 cfgerr++;
4688 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004689 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4690 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004691 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004692 } else {
4693 free(curproxy->defbe.name);
4694 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004695 /* we force the backend to be present on at least all of
4696 * the frontend's processes.
4697 */
4698 target->bind_proc = curproxy->bind_proc ?
4699 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 }
4701 }
4702
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004703 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004704 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4705 /* map jump target for ACT_SETBE in req_rep chain */
4706 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004707 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004708 struct proxy *target;
4709
Willy Tarreaua496b602006-12-17 23:15:24 +01004710 if (exp->action != ACT_SETBE)
4711 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004712
Alex Williams96532db2009-11-01 21:27:13 -05004713 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004714 if (!target) {
4715 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4716 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004717 cfgerr++;
4718 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004719 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4720 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004721 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004722 } else {
4723 free((void *)exp->replace);
4724 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004725 /* we force the backend to be present on at least all of
4726 * the frontend's processes.
4727 */
4728 target->bind_proc = curproxy->bind_proc ?
4729 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004730 }
4731 }
4732 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004733
4734 /* find the target proxy for 'use_backend' rules */
4735 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004736 struct proxy *target;
4737
Alex Williams96532db2009-11-01 21:27:13 -05004738 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004739
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004740 if (!target) {
4741 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4742 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004743 cfgerr++;
4744 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004745 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4746 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004747 cfgerr++;
4748 } else {
4749 free((void *)rule->be.name);
4750 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004751 /* we force the backend to be present on at least all of
4752 * the frontend's processes.
4753 */
4754 target->bind_proc = curproxy->bind_proc ?
4755 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004756 }
4757 }
4758
Emeric Brunb982a3d2010-01-04 15:45:53 +01004759 /* find the target table for 'stick' rules */
4760 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4761 struct proxy *target;
4762
Emeric Brun1d33b292010-01-04 15:47:17 +01004763 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4764 if (mrule->flags & STK_IS_STORE)
4765 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4766
Emeric Brunb982a3d2010-01-04 15:45:53 +01004767 if (mrule->table.name)
4768 target = findproxy(mrule->table.name, PR_CAP_BE);
4769 else
4770 target = curproxy;
4771
4772 if (!target) {
4773 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4774 curproxy->id, mrule->table.name);
4775 cfgerr++;
4776 }
4777 else if (target->table.size == 0) {
4778 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4779 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4780 cfgerr++;
4781 }
4782 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4783 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4784 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4785 cfgerr++;
4786 }
4787 else {
4788 free((void *)mrule->table.name);
4789 mrule->table.t = &(target->table);
4790 }
4791 }
4792
4793 /* find the target table for 'store response' rules */
4794 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4795 struct proxy *target;
4796
Emeric Brun1d33b292010-01-04 15:47:17 +01004797 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4798
Emeric Brunb982a3d2010-01-04 15:45:53 +01004799 if (mrule->table.name)
4800 target = findproxy(mrule->table.name, PR_CAP_BE);
4801 else
4802 target = curproxy;
4803
4804 if (!target) {
4805 Alert("Proxy '%s': unable to find store table '%s'.\n",
4806 curproxy->id, mrule->table.name);
4807 cfgerr++;
4808 }
4809 else if (target->table.size == 0) {
4810 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4811 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4812 cfgerr++;
4813 }
4814 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4815 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4816 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4817 cfgerr++;
4818 }
4819 else {
4820 free((void *)mrule->table.name);
4821 mrule->table.t = &(target->table);
4822 }
4823 }
4824
Willy Tarreau2738a142006-07-08 17:28:09 +02004825 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004826 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004827 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004828 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004829 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004830 " | While not properly invalid, you will certainly encounter various problems\n"
4831 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004832 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004833 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004834 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004835 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004836
Willy Tarreau1fa31262007-12-03 00:36:16 +01004837 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4838 * We must still support older configurations, so let's find out whether those
4839 * parameters have been set or must be copied from contimeouts.
4840 */
4841 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004842 if (!curproxy->timeout.tarpit ||
4843 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004844 /* tarpit timeout not set. We search in the following order:
4845 * default.tarpit, curr.connect, default.connect.
4846 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004847 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004848 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004849 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004850 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004851 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004852 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004853 }
4854 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004855 (!curproxy->timeout.queue ||
4856 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004857 /* queue timeout not set. We search in the following order:
4858 * default.queue, curr.connect, default.connect.
4859 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004860 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004861 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004862 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004863 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004864 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004865 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004866 }
4867 }
4868
Willy Tarreauf3c69202006-07-09 16:42:34 +02004869 if (curproxy->options & PR_O_SSL3_CHK) {
4870 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4871 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4872 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4873 }
4874
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004875 /* The small pools required for the capture lists */
4876 if (curproxy->nb_req_cap)
4877 curproxy->req_cap_pool = create_pool("ptrcap",
4878 curproxy->nb_req_cap * sizeof(char *),
4879 MEM_F_SHARED);
4880 if (curproxy->nb_rsp_cap)
4881 curproxy->rsp_cap_pool = create_pool("ptrcap",
4882 curproxy->nb_rsp_cap * sizeof(char *),
4883 MEM_F_SHARED);
4884
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004885 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4886 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4887 MEM_F_SHARED);
4888
Willy Tarreau86034312006-12-29 00:10:33 +01004889 /* for backwards compatibility with "listen" instances, if
4890 * fullconn is not set but maxconn is set, then maxconn
4891 * is used.
4892 */
4893 if (!curproxy->fullconn)
4894 curproxy->fullconn = curproxy->maxconn;
4895
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 /* first, we will invert the servers list order */
4897 newsrv = NULL;
4898 while (curproxy->srv) {
4899 struct server *next;
4900
4901 next = curproxy->srv->next;
4902 curproxy->srv->next = newsrv;
4903 newsrv = curproxy->srv;
4904 if (!next)
4905 break;
4906 curproxy->srv = next;
4907 }
4908
Willy Tarreau20697042007-11-15 23:26:18 +01004909 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004910 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004912 /* We have to initialize the server lookup mechanism depending
4913 * on what LB algorithm was choosen.
4914 */
4915
4916 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4917 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4918 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004919 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4920 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4921 init_server_map(curproxy);
4922 } else {
4923 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4924 fwrr_init_server_groups(curproxy);
4925 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004926 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004927
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004928 case BE_LB_KIND_LC:
4929 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004930 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004931 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004932
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004933 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004934 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4935 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4936 chash_init_server_tree(curproxy);
4937 } else {
4938 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4939 init_server_map(curproxy);
4940 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004941 break;
4942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943
4944 if (curproxy->options & PR_O_LOGASAP)
4945 curproxy->to_log &= ~LW_BYTES;
4946
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004947 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4948 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4949 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4950 proxy_type_str(curproxy), curproxy->id);
4951 err_code |= ERR_WARN;
4952 }
4953
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004955 * ensure that we're not cross-dressing a TCP server into HTTP.
4956 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004957 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004958 newsrv = curproxy->srv;
4959 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004960 if (!newsrv->puid) {
4961 /* server ID not set, use automatic numbering with first
4962 * spare entry starting with next_svid.
4963 */
4964 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4965 newsrv->conf.id.key = newsrv->puid = next_id;
4966 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4967 next_id++;
4968 }
4969
Willy Tarreau21d2af32008-02-14 20:25:24 +01004970 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004971 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4972 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004973 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004974 }
4975 newsrv = newsrv->next;
4976 }
4977
4978 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 * If this server supports a maxconn parameter, it needs a dedicated
4980 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004981 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 */
4983 newsrv = curproxy->srv;
4984 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004985 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 /* Only 'minconn' was specified, or it was higher than or equal
4987 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4988 * this will avoid further useless expensive computations.
4989 */
4990 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004991 } else if (newsrv->maxconn && !newsrv->minconn) {
4992 /* minconn was not specified, so we set it to maxconn */
4993 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004995 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4996 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004997 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
4999
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005000 if (newsrv->trackit) {
5001 struct proxy *px;
5002 struct server *srv;
5003 char *pname, *sname;
5004
5005 pname = newsrv->trackit;
5006 sname = strrchr(pname, '/');
5007
5008 if (sname)
5009 *sname++ = '\0';
5010 else {
5011 sname = pname;
5012 pname = NULL;
5013 }
5014
5015 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05005016 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005017 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005018 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
5019 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005020 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005021 cfgerr++;
5022 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005023 }
5024 } else
5025 px = curproxy;
5026
5027 srv = findserver(px, sname);
5028 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005029 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
5030 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005031 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02005032 cfgerr++;
5033 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005034 }
5035
5036 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005037 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005038 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005039 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005040 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005041 cfgerr++;
5042 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005043 }
5044
5045 if (curproxy != px &&
5046 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005047 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005048 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005049 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005050 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005051 cfgerr++;
5052 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005053 }
5054
5055 newsrv->tracked = srv;
5056 newsrv->tracknext = srv->tracknext;
5057 srv->tracknext = newsrv;
5058
5059 free(newsrv->trackit);
5060 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005061 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 newsrv = newsrv->next;
5063 }
5064
Willy Tarreauc1a21672009-08-16 22:37:44 +02005065 if (curproxy->cap & PR_CAP_FE) {
5066 if (curproxy->tcp_req.inspect_delay ||
5067 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5068 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5069
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005070 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005071 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005072 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005073 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005074
5075 /* both TCP and HTTP must check switching rules */
5076 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5077 }
5078
5079 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005080 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005081 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005082 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005083 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005084
Emeric Brunb982a3d2010-01-04 15:45:53 +01005085 /* init table on backend capabilities proxy */
5086 stktable_init(&curproxy->table);
5087
Willy Tarreauc1a21672009-08-16 22:37:44 +02005088 /* If the backend does requires RDP cookie persistence, we have to
5089 * enable the corresponding analyser.
5090 */
5091 if (curproxy->options2 & PR_O2_RDPC_PRST)
5092 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5093 }
5094
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005095 listener = NULL;
5096 while (curproxy->listen) {
5097 struct listener *next;
5098
5099 next = curproxy->listen->next;
5100 curproxy->listen->next = listener;
5101 listener = curproxy->listen;
5102
5103 if (!next)
5104 break;
5105
5106 curproxy->listen = next;
5107 }
5108
Willy Tarreaue6b98942007-10-29 01:09:36 +01005109 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005110 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005111 listener = curproxy->listen;
5112 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005113 if (!listener->luid) {
5114 /* listener ID not set, use automatic numbering with first
5115 * spare entry starting with next_luid.
5116 */
5117 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5118 listener->conf.id.key = listener->luid = next_id;
5119 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
5120 next_id++;
5121 }
5122
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005123 /* enable separate counters */
5124 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5125 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5126 if (!listener->name) {
5127 sprintf(trash, "sock-%d", listener->luid);
5128 listener->name = strdup(trash);
5129 }
5130 }
5131
Willy Tarreaue6b98942007-10-29 01:09:36 +01005132 if (curproxy->options & PR_O_TCP_NOLING)
5133 listener->options |= LI_O_NOLINGER;
5134 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005135 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005136 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005137 listener->accept = event_accept;
5138 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005139 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005140 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005141
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005142 /* smart accept mode is automatic in HTTP mode */
5143 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5144 (curproxy->mode == PR_MODE_HTTP &&
5145 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5146 listener->options |= LI_O_NOQUICKACK;
5147
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005148 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005149 listener = listener->next;
5150 }
5151
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 curproxy = curproxy->next;
5153 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005154
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005155 /*
5156 * Recount currently required checks.
5157 */
5158
5159 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5160 int optnum;
5161
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005162 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5163 if (curproxy->options & cfg_opts[optnum].val)
5164 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005165
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005166 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5167 if (curproxy->options2 & cfg_opts2[optnum].val)
5168 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005169 }
5170
Willy Tarreaubb925012009-07-23 13:36:36 +02005171 if (cfgerr > 0)
5172 err_code |= ERR_ALERT | ERR_FATAL;
5173 out:
5174 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175}
5176
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005177/*
5178 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5179 * parsing sessions.
5180 */
5181void cfg_register_keywords(struct cfg_kw_list *kwl)
5182{
5183 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5184}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005186/*
5187 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5188 */
5189void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5190{
5191 LIST_DEL(&kwl->list);
5192 LIST_INIT(&kwl->list);
5193}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194
5195/*
5196 * Local variables:
5197 * c-indent-level: 8
5198 * c-basic-offset: 8
5199 * End:
5200 */