blob: 7bb94b83637be0b21447b99580c80890c0fdf4e0 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 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 Tarreauf89c1872009-10-01 11:19:37 +020045#include <proto/lb_fwlc.h>
46#include <proto/lb_fwrr.h>
47#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020049#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010050#include <proto/protocols.h>
51#include <proto/proto_tcp.h>
52#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010053#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010055#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/task.h>
57
58
Willy Tarreauf3c69202006-07-09 16:42:34 +020059/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
60 * ssl-hello-chk option to ensure that the remote server speaks SSL.
61 *
62 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
63 */
64const char sslv3_client_hello_pkt[] = {
65 "\x16" /* ContentType : 0x16 = Hanshake */
66 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
67 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
68 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
69 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
70 "\x03\x00" /* Hello Version : 0x0300 = v3 */
71 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
72 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
73 "\x00" /* Session ID length : empty (no session ID) */
74 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
75 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
76 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
77 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
78 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
79 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
80 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
81 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
82 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
83 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
84 "\x00\x38" "\x00\x39" "\x00\x3A"
85 "\x01" /* Compression Length : 0x01 = 1 byte for types */
86 "\x00" /* Compression Type : 0x00 = NULL compression */
87};
88
Willy Tarreau3842f002009-06-14 11:39:52 +020089/* various keyword modifiers */
90enum kw_mod {
91 KWM_STD = 0, /* normal */
92 KWM_NO, /* "no" prefixed before the keyword */
93 KWM_DEF, /* "default" prefixed before the keyword */
94};
95
Willy Tarreau13943ab2006-12-31 00:24:10 +010096/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010097struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010098 const char *name;
99 unsigned int val;
100 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100101 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100102};
103
104/* proxy->options */
105static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100108 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100111 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
112 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
113 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
114 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
115 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
116 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
117 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
118 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100120 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
121 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100122#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100123 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100124#endif
125
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100126 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127};
128
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100129/* proxy->options2 */
130static const struct cfg_opt cfg_opts2[] =
131{
132#ifdef CONFIG_HAP_LINUX_SPLICE
133 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
134 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
135 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
136#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200137 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
138 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200139 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
140 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200141 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200142 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200143 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144 { NULL, 0, 0, 0 }
145};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146
Willy Tarreau6daf3432008-01-22 16:44:08 +0100147static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200148static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
149int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100150int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200151
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200152/* List head of all known configuration keywords */
153static struct cfg_kw_list cfg_keywords = {
154 .list = LIST_HEAD_INIT(cfg_keywords.list)
155};
156
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157/*
158 * converts <str> to a list of listeners which are dynamically allocated.
159 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
160 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
161 * - <port> is a numerical port from 1 to 65535 ;
162 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
163 * This can be repeated as many times as necessary, separated by a coma.
164 * The <tail> argument is a pointer to a current list which should be appended
165 * to the tail of the new list. The pointer to the new list is returned.
166 */
167static struct listener *str2listener(char *str, struct listener *tail)
168{
169 struct listener *l;
170 char *c, *next, *range, *dupstr;
171 int port, end;
172
173 next = dupstr = strdup(str);
174
175 while (next && *next) {
176 struct sockaddr_storage ss;
177
178 str = next;
179 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100180 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181 *next++ = 0;
182 }
183
184 /* 2) look for the addr/port delimiter, it's the last colon. */
185 if ((range = strrchr(str, ':')) == NULL) {
186 Alert("Missing port number: '%s'\n", str);
187 goto fail;
188 }
189
190 *range++ = 0;
191
192 if (strrchr(str, ':') != NULL) {
193 /* IPv6 address contains ':' */
194 memset(&ss, 0, sizeof(ss));
195 ss.ss_family = AF_INET6;
196
197 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
198 Alert("Invalid server address: '%s'\n", str);
199 goto fail;
200 }
201 }
202 else {
203 memset(&ss, 0, sizeof(ss));
204 ss.ss_family = AF_INET;
205
206 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
207 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
208 }
209 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
210 struct hostent *he;
211
212 if ((he = gethostbyname(str)) == NULL) {
213 Alert("Invalid server name: '%s'\n", str);
214 goto fail;
215 }
216 else
217 ((struct sockaddr_in *)&ss)->sin_addr =
218 *(struct in_addr *) *(he->h_addr_list);
219 }
220 }
221
222 /* 3) look for the port-end delimiter */
223 if ((c = strchr(range, '-')) != NULL) {
224 *c++ = 0;
225 end = atol(c);
226 }
227 else {
228 end = atol(range);
229 }
230
231 port = atol(range);
232
233 if (port < 1 || port > 65535) {
234 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
235 goto fail;
236 }
237
238 if (end < 1 || end > 65535) {
239 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
240 goto fail;
241 }
242
243 for (; port <= end; port++) {
244 l = (struct listener *)calloc(1, sizeof(struct listener));
245 l->next = tail;
246 tail = l;
247
248 l->fd = -1;
249 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100250 l->state = LI_INIT;
251
252 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100254 tcpv6_add_listener(l);
255 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100257 tcpv4_add_listener(l);
258 }
259 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 } /* end for(port) */
261 } /* end while(next) */
262 free(dupstr);
263 return tail;
264 fail:
265 free(dupstr);
266 return NULL;
267}
268
Willy Tarreau977b8e42006-12-29 14:19:17 +0100269/*
270 * Sends a warning if proxy <proxy> does not have at least one of the
271 * capabilities in <cap>. An optionnal <hint> may be added at the end
272 * of the warning to help the user. Returns 1 if a warning was emitted
273 * or 0 if the condition is valid.
274 */
275int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
276{
277 char *msg;
278
279 switch (cap) {
280 case PR_CAP_BE: msg = "no backend"; break;
281 case PR_CAP_FE: msg = "no frontend"; break;
282 case PR_CAP_RS: msg = "no ruleset"; break;
283 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
284 default: msg = "not enough"; break;
285 }
286
287 if (!(proxy->cap & cap)) {
288 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100289 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100290 return 1;
291 }
292 return 0;
293}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294
Willy Tarreau61d18892009-03-31 10:49:21 +0200295/* Report a warning if a rule is placed after a 'block' rule.
296 * Return 1 if the warning has been emitted, otherwise 0.
297 */
298int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
299{
300 if (!LIST_ISEMPTY(&proxy->block_cond)) {
301 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
302 file, line, arg);
303 return 1;
304 }
305 return 0;
306}
307
308/* Report a warning if a rule is placed after a reqrewrite rule.
309 * Return 1 if the warning has been emitted, otherwise 0.
310 */
311int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
312{
313 if (proxy->req_exp) {
314 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
315 file, line, arg);
316 return 1;
317 }
318 return 0;
319}
320
321/* Report a warning if a rule is placed after a reqadd rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
325{
326 if (proxy->nb_reqadd) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
334/* Report a warning if a rule is placed after a redirect rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
337int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
338{
339 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
347/* Report a warning if a rule is placed after a 'use_backend' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
360/* report a warning if a block rule is dangerously placed */
361int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
362{
363 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
364 warnif_rule_after_reqadd(proxy, file, line, arg) ||
365 warnif_rule_after_redirect(proxy, file, line, arg) ||
366 warnif_rule_after_use_backend(proxy, file, line, arg);
367}
368
369/* report a warning if a reqxxx rule is dangerously placed */
370int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
371{
372 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
373 warnif_rule_after_redirect(proxy, file, line, arg) ||
374 warnif_rule_after_use_backend(proxy, file, line, arg);
375}
376
377/* report a warning if a reqadd rule is dangerously placed */
378int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
379{
380 return warnif_rule_after_redirect(proxy, file, line, arg) ||
381 warnif_rule_after_use_backend(proxy, file, line, arg);
382}
383
Willy Tarreaubaaee002006-06-26 02:48:02 +0200384/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200385 * parse a line in a <global> section. Returns the error code, 0 if OK, or
386 * any combination of :
387 * - ERR_ABORT: must abort ASAP
388 * - ERR_FATAL: we can continue parsing but not start the service
389 * - ERR_WARN: a warning has been emitted
390 * - ERR_ALERT: an alert has been emitted
391 * Only the two first ones can stop processing, the two others are just
392 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200393 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200394int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395{
Willy Tarreau058e9072009-07-20 09:30:05 +0200396 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397
398 if (!strcmp(args[0], "global")) { /* new section */
399 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401 }
402 else if (!strcmp(args[0], "daemon")) {
403 global.mode |= MODE_DAEMON;
404 }
405 else if (!strcmp(args[0], "debug")) {
406 global.mode |= MODE_DEBUG;
407 }
408 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100409 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200410 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200411 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100412 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200413 }
414 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100415 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200417 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100418 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200419 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100420 else if (!strcmp(args[0], "nosplice")) {
421 global.tune.options &= ~GTUNE_USE_SPLICE;
422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200423 else if (!strcmp(args[0], "quiet")) {
424 global.mode |= MODE_QUIET;
425 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200426 else if (!strcmp(args[0], "tune.maxpollevents")) {
427 if (global.tune.maxpollevents != 0) {
428 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200429 err_code |= ERR_ALERT;
430 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200431 }
432 if (*(args[1]) == 0) {
433 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200434 err_code |= ERR_ALERT | ERR_FATAL;
435 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200436 }
437 global.tune.maxpollevents = atol(args[1]);
438 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100439 else if (!strcmp(args[0], "tune.maxaccept")) {
440 if (global.tune.maxaccept != 0) {
441 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200442 err_code |= ERR_ALERT;
443 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100444 }
445 if (*(args[1]) == 0) {
446 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200447 err_code |= ERR_ALERT | ERR_FATAL;
448 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100449 }
450 global.tune.maxaccept = atol(args[1]);
451 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200452 else if (!strcmp(args[0], "tune.bufsize")) {
453 if (*(args[1]) == 0) {
454 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
455 err_code |= ERR_ALERT | ERR_FATAL;
456 goto out;
457 }
458 global.tune.bufsize = atol(args[1]);
459 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
460 global.tune.maxrewrite = global.tune.bufsize / 2;
461 }
462 else if (!strcmp(args[0], "tune.maxrewrite")) {
463 if (*(args[1]) == 0) {
464 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
465 err_code |= ERR_ALERT | ERR_FATAL;
466 goto out;
467 }
468 global.tune.maxrewrite = atol(args[1]);
469 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
470 global.tune.maxrewrite = global.tune.bufsize / 2;
471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472 else if (!strcmp(args[0], "uid")) {
473 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200474 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200475 err_code |= ERR_ALERT;
476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 }
483 global.uid = atol(args[1]);
484 }
485 else if (!strcmp(args[0], "gid")) {
486 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200487 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495 }
496 global.gid = atol(args[1]);
497 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200498 /* user/group name handling */
499 else if (!strcmp(args[0], "user")) {
500 struct passwd *ha_user;
501 if (global.uid != 0) {
502 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT;
504 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200505 }
506 errno = 0;
507 ha_user = getpwnam(args[1]);
508 if (ha_user != NULL) {
509 global.uid = (int)ha_user->pw_uid;
510 }
511 else {
512 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 +0200513 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200514 }
515 }
516 else if (!strcmp(args[0], "group")) {
517 struct group *ha_group;
518 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200519 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200520 err_code |= ERR_ALERT;
521 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200522 }
523 errno = 0;
524 ha_group = getgrnam(args[1]);
525 if (ha_group != NULL) {
526 global.gid = (int)ha_group->gr_gid;
527 }
528 else {
529 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 +0200530 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200531 }
532 }
533 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200534 else if (!strcmp(args[0], "nbproc")) {
535 if (global.nbproc != 0) {
536 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200537 err_code |= ERR_ALERT;
538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 }
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544 }
545 global.nbproc = atol(args[1]);
546 }
547 else if (!strcmp(args[0], "maxconn")) {
548 if (global.maxconn != 0) {
549 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200550 err_code |= ERR_ALERT;
551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
553 if (*(args[1]) == 0) {
554 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200555 err_code |= ERR_ALERT | ERR_FATAL;
556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557 }
558 global.maxconn = atol(args[1]);
559#ifdef SYSTEM_MAXCONN
560 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
561 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);
562 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200563 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 }
565#endif /* SYSTEM_MAXCONN */
566 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100567 else if (!strcmp(args[0], "maxpipes")) {
568 if (global.maxpipes != 0) {
569 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT;
571 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100572 }
573 if (*(args[1]) == 0) {
574 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT | ERR_FATAL;
576 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100577 }
578 global.maxpipes = atol(args[1]);
579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 else if (!strcmp(args[0], "ulimit-n")) {
581 if (global.rlimit_nofile != 0) {
582 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT;
584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 global.rlimit_nofile = atol(args[1]);
592 }
593 else if (!strcmp(args[0], "chroot")) {
594 if (global.chroot != NULL) {
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 a directory as an 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.chroot = strdup(args[1]);
605 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200606 else if (!strcmp(args[0], "description")) {
607 int i, len=0;
608 char *d;
609
610 if (!*args[1]) {
611 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
612 file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616
617 for(i=1; *args[i]; i++)
618 len += strlen(args[i])+1;
619
620 if (global.desc)
621 free(global.desc);
622
623 global.desc = d = (char *)calloc(1, len);
624
625 d += sprintf(d, "%s", args[1]);
626 for(i=2; *args[i]; i++)
627 d += sprintf(d, " %s", args[i]);
628 }
629 else if (!strcmp(args[0], "node")) {
630 int i;
631 char c;
632
633 for (i=0; args[1][i]; i++) {
634 c = args[1][i];
635 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
636 break;
637 }
638
639 if (!i || args[1][i]) {
640 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
641 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
642 file, linenum, args[0]);
643 err_code |= ERR_ALERT | ERR_FATAL;
644 goto out;
645 }
646
647 if (global.node)
648 free(global.node);
649
650 global.node = strdup(args[1]);
651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "pidfile")) {
653 if (global.pidfile != 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 file name 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.pidfile = strdup(args[1]);
664 }
665 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100666 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200667 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668
669 if (*(args[1]) == 0 || *(args[2]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 }
674
675 facility = get_log_facility(args[2]);
676 if (facility < 0) {
677 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681
682 level = 7; /* max syslog level = debug */
683 if (*(args[3])) {
684 level = get_log_level(args[3]);
685 if (level < 0) {
686 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
688 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 }
690 }
691
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200692 minlvl = 0; /* limit syslog level to this level (emerg) */
693 if (*(args[4])) {
694 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200696 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200699 }
700 }
701
Robert Tsai81ae1952007-12-05 10:47:29 +0100702 if (args[1][0] == '/') {
703 logsrv.u.addr.sa_family = AF_UNIX;
704 logsrv.u.un = *str2sun(args[1]);
705 } else {
706 logsrv.u.addr.sa_family = AF_INET;
707 logsrv.u.in = *str2sa(args[1]);
708 if (!logsrv.u.in.sin_port)
709 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711
712 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100713 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 global.logfac1 = facility;
715 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200716 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 }
718 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100719 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 global.logfac2 = facility;
721 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200722 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 }
724 else {
725 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200726 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200728 }
729 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
730 if (global.spread_checks != 0) {
731 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT;
733 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200734 }
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200739 }
740 global.spread_checks = atol(args[1]);
741 if (global.spread_checks < 0 || global.spread_checks > 50) {
742 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200747 struct cfg_kw_list *kwl;
748 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200749 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200750
751 list_for_each_entry(kwl, &cfg_keywords.list, list) {
752 for (index = 0; kwl->kw[index].kw != NULL; index++) {
753 if (kwl->kw[index].section != CFG_GLOBAL)
754 continue;
755 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
756 /* prepare error message just in case */
757 snprintf(trash, sizeof(trash),
758 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200759 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
760 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200761 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200763 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200764 else if (rc > 0) {
765 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_WARN;
767 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200768 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200770 }
771 }
772 }
773
Willy Tarreaubaaee002006-06-26 02:48:02 +0200774 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200777
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 out:
779 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780}
781
782
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200783void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784{
785 memset(&defproxy, 0, sizeof(defproxy));
786 defproxy.mode = PR_MODE_TCP;
787 defproxy.state = PR_STNEW;
788 defproxy.maxconn = cfg_maxpconn;
789 defproxy.conn_retries = CONN_RETRIES;
790 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200791
792 LIST_INIT(&defproxy.pendconns);
793 LIST_INIT(&defproxy.acl);
794 LIST_INIT(&defproxy.block_cond);
795 LIST_INIT(&defproxy.mon_fail_cond);
796 LIST_INIT(&defproxy.switching_rules);
797
Willy Tarreau3a70f942008-02-15 11:15:34 +0100798 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799}
800
801/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100802 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200803 * Returns the error code, 0 if OK, or any combination of :
804 * - ERR_ABORT: must abort ASAP
805 * - ERR_FATAL: we can continue parsing but not start the service
806 * - ERR_WARN: a warning has been emitted
807 * - ERR_ALERT: an alert has been emitted
808 * Only the two first ones can stop processing, the two others are just
809 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200810 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200811int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812{
813 static struct proxy *curproxy = NULL;
814 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200815 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100816 int rc;
817 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200818 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819
Willy Tarreau977b8e42006-12-29 14:19:17 +0100820 if (!strcmp(args[0], "listen"))
821 rc = PR_CAP_LISTEN;
822 else if (!strcmp(args[0], "frontend"))
823 rc = PR_CAP_FE | PR_CAP_RS;
824 else if (!strcmp(args[0], "backend"))
825 rc = PR_CAP_BE | PR_CAP_RS;
826 else if (!strcmp(args[0], "ruleset"))
827 rc = PR_CAP_RS;
828 else
829 rc = PR_CAP_NONE;
830
831 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 if (!*args[1]) {
833 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
834 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
835 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200836 err_code |= ERR_ALERT | ERR_ABORT;
837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200839
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100840 err = invalid_char(args[1]);
841 if (err) {
842 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
843 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200844 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100845 }
846
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200847 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
848 /*
849 * If there are two proxies with the same name only following
850 * combinations are allowed:
851 *
852 * listen backend frontend ruleset
853 * listen - - - -
854 * backend - - OK -
855 * frontend - OK - -
856 * ruleset - - - -
857 */
858
859 if (!strcmp(curproxy->id, args[1]) &&
860 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
861 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100862 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
863 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Willy Tarreau93893792009-07-23 13:19:11 +0200864 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200865 }
866 }
867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
869 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200870 err_code |= ERR_ALERT | ERR_ABORT;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100873
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874 curproxy->next = proxy;
875 proxy = curproxy;
876 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200877 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200878 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200879 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100880 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200881 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200882 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883
Willy Tarreauee991362007-05-14 14:37:50 +0200884 /* Timeouts are defined as -1, so we cannot use the zeroed area
885 * as a default value.
886 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100887 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200888
889 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100891 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892
893 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100894 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 curproxy->listen = str2listener(args[2], curproxy->listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200896 if (!curproxy->listen) {
897 err_code |= ERR_FATAL;
898 goto out;
899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 global.maxsock++;
901 }
902
903 /* set default values */
904 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100906 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200907 curproxy->no_options = defproxy.no_options;
908 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100909 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100910 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200911 curproxy->except_net = defproxy.except_net;
912 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200913 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200914 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200916 if (defproxy.fwdfor_hdr_len) {
917 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
918 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
919 }
920
Willy Tarreau977b8e42006-12-29 14:19:17 +0100921 if (curproxy->cap & PR_CAP_FE) {
922 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100923 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200924 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100925
926 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200927 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
928 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100929
930 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 if (curproxy->cap & PR_CAP_BE) {
934 curproxy->fullconn = defproxy.fullconn;
935 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936
Willy Tarreau977b8e42006-12-29 14:19:17 +0100937 if (defproxy.check_req)
938 curproxy->check_req = strdup(defproxy.check_req);
939 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940
Willy Tarreau977b8e42006-12-29 14:19:17 +0100941 if (defproxy.cookie_name)
942 curproxy->cookie_name = strdup(defproxy.cookie_name);
943 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100944
Emeric Brun647caf12009-06-30 17:57:00 +0200945 if (defproxy.rdp_cookie_name)
946 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
947 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
948
Willy Tarreau01732802007-11-01 22:48:15 +0100949 if (defproxy.url_param_name)
950 curproxy->url_param_name = strdup(defproxy.url_param_name);
951 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100952
Benoitaffb4812009-03-25 13:02:10 +0100953 if (defproxy.hh_name)
954 curproxy->hh_name = strdup(defproxy.hh_name);
955 curproxy->hh_len = defproxy.hh_len;
956 curproxy->hh_match_domain = defproxy.hh_match_domain;
957
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100958 if (defproxy.iface_name)
959 curproxy->iface_name = strdup(defproxy.iface_name);
960 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200963 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100964 if (defproxy.capture_name)
965 curproxy->capture_name = strdup(defproxy.capture_name);
966 curproxy->capture_namelen = defproxy.capture_namelen;
967 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969
Willy Tarreau977b8e42006-12-29 14:19:17 +0100970 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100971 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100972 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100973 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100974 curproxy->uri_auth = defproxy.uri_auth;
975 curproxy->mon_net = defproxy.mon_net;
976 curproxy->mon_mask = defproxy.mon_mask;
977 if (defproxy.monitor_uri)
978 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
979 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100980 if (defproxy.defbe.name)
981 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100982 }
983
984 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100985 curproxy->timeout.connect = defproxy.timeout.connect;
986 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100987 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100988 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100989 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +0200990 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100991 curproxy->source_addr = defproxy.source_addr;
992 }
993
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 curproxy->mode = defproxy.mode;
995 curproxy->logfac1 = defproxy.logfac1;
996 curproxy->logsrv1 = defproxy.logsrv1;
997 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200998 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 curproxy->logfac2 = defproxy.logfac2;
1000 curproxy->logsrv2 = defproxy.logsrv2;
1001 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001002 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001004 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
1005 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +02001006
Willy Tarreau93893792009-07-23 13:19:11 +02001007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 }
1009 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1010 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001011 /* FIXME-20070101: we should do this too at the end of the
1012 * config parsing to free all default values.
1013 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001014 free(defproxy.check_req);
1015 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001016 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001017 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001018 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001019 free(defproxy.capture_name);
1020 free(defproxy.monitor_uri);
1021 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001022 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001023 free(defproxy.fwdfor_hdr_name);
1024 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001025
Willy Tarreaua534fea2008-08-03 12:19:50 +02001026 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001027 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001028
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 /* we cannot free uri_auth because it might already be used */
1030 init_default_instance();
1031 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001032 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 }
1035 else if (curproxy == NULL) {
1036 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 }
1040
Willy Tarreau977b8e42006-12-29 14:19:17 +01001041
1042 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001044 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001045 int cur_arg;
1046
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 if (curproxy == &defproxy) {
1048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001049 err_code |= ERR_ALERT | ERR_FATAL;
1050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001052 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001053 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054
1055 if (strchr(args[1], ':') == NULL) {
1056 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001061
1062 last_listen = curproxy->listen;
1063 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreau93893792009-07-23 13:19:11 +02001064 if (!curproxy->listen) {
1065 err_code |= ERR_ALERT | ERR_FATAL;
1066 goto out;
1067 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001068
1069 cur_arg = 2;
1070 while (*(args[cur_arg])) {
1071 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1072#ifdef SO_BINDTODEVICE
1073 struct listener *l;
1074
1075 if (!*args[cur_arg + 1]) {
1076 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1077 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001080 }
1081
1082 for (l = curproxy->listen; l != last_listen; l = l->next)
1083 l->interface = strdup(args[cur_arg + 1]);
1084
1085 global.last_checks |= LSTCHK_NETADM;
1086
1087 cur_arg += 2;
1088 continue;
1089#else
1090 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1091 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001094#endif
1095 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001096 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1097#ifdef TCP_MAXSEG
1098 struct listener *l;
1099 int mss;
1100
1101 if (!*args[cur_arg + 1]) {
1102 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001106 }
1107
1108 mss = str2uic(args[cur_arg + 1]);
1109 if (mss < 1 || mss > 65535) {
1110 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001114 }
1115
1116 for (l = curproxy->listen; l != last_listen; l = l->next)
1117 l->maxseg = mss;
1118
1119 cur_arg += 2;
1120 continue;
1121#else
1122 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1123 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001126#endif
1127 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001128 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001129#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001130 struct listener *l;
1131
1132 for (l = curproxy->listen; l != last_listen; l = l->next)
1133 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001134
1135 cur_arg ++;
1136 continue;
1137#else
1138 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1139 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001142#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001143 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001144 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1153 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1154 Alert("parsing [%s:%d] : '%s' expects address[/mask].\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 Tarreau977b8e42006-12-29 14:19:17 +01001159 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001160 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001161
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 /* flush useless bits */
1163 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001166 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001167 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001168 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169
Willy Tarreau1c47f852006-07-09 08:22:27 +02001170 if (!*args[1]) {
1171 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1172 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001173 err_code |= ERR_ALERT | ERR_FATAL;
1174 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001175 }
1176
Willy Tarreaua534fea2008-08-03 12:19:50 +02001177 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001178 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001179 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001180 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001181 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1182
Willy Tarreau93893792009-07-23 13:19:11 +02001183 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001185 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1186 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1187 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1188 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1189 else {
1190 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
1194 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001195 else if (!strcmp(args[0], "id")) {
1196 struct proxy *target;
1197
1198 if (curproxy == &defproxy) {
1199 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001203 }
1204
1205 if (!*args[1]) {
1206 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1207 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001210 }
1211
1212 curproxy->uuid = atol(args[1]);
1213
1214 if (curproxy->uuid < 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02001215 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001219 }
1220
1221 for (target = proxy; target; target = target->next)
1222 if (curproxy != target && curproxy->uuid == target->uuid) {
1223 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1224 file, linenum, curproxy->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02001225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001227 }
1228 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001229 else if (!strcmp(args[0], "description")) {
1230 int i, len=0;
1231 char *d;
1232
1233 if (!*args[1]) {
1234 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1235 file, linenum, args[0]);
1236 return -1;
1237 }
1238
1239 for(i=1; *args[i]; i++)
1240 len += strlen(args[i])+1;
1241
1242 d = (char *)calloc(1, len);
1243 curproxy->desc = d;
1244
1245 d += sprintf(d, "%s", args[1]);
1246 for(i=2; *args[i]; i++)
1247 d += sprintf(d, " %s", args[i]);
1248
1249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1251 curproxy->state = PR_STSTOPPED;
1252 }
1253 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1254 curproxy->state = PR_STNEW;
1255 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001256 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1257 int cur_arg = 1;
1258 unsigned int set = 0;
1259
1260 while (*args[cur_arg]) {
1261 int u;
1262 if (strcmp(args[cur_arg], "all") == 0) {
1263 set = 0;
1264 break;
1265 }
1266 else if (strcmp(args[cur_arg], "odd") == 0) {
1267 set |= 0x55555555;
1268 }
1269 else if (strcmp(args[cur_arg], "even") == 0) {
1270 set |= 0xAAAAAAAA;
1271 }
1272 else {
1273 u = str2uic(args[cur_arg]);
1274 if (u < 1 || u > 32) {
1275 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001279 }
1280 if (u > global.nbproc) {
1281 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001284 }
1285 set |= 1 << (u - 1);
1286 }
1287 cur_arg++;
1288 }
1289 curproxy->bind_proc = set;
1290 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001291 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001292 if (curproxy == &defproxy) {
1293 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001294 err_code |= ERR_ALERT | ERR_FATAL;
1295 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001296 }
1297
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001298 err = invalid_char(args[1]);
1299 if (err) {
1300 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1301 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001302 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001303 }
1304
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001305 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1306 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1307 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001310 }
1311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1313 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314
Willy Tarreau977b8e42006-12-29 14:19:17 +01001315 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001316 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001317
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 if (*(args[1]) == 0) {
1319 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001324
1325 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 curproxy->cookie_name = strdup(args[1]);
1327 curproxy->cookie_len = strlen(curproxy->cookie_name);
1328
1329 cur_arg = 2;
1330 while (*(args[cur_arg])) {
1331 if (!strcmp(args[cur_arg], "rewrite")) {
1332 curproxy->options |= PR_O_COOK_RW;
1333 }
1334 else if (!strcmp(args[cur_arg], "indirect")) {
1335 curproxy->options |= PR_O_COOK_IND;
1336 }
1337 else if (!strcmp(args[cur_arg], "insert")) {
1338 curproxy->options |= PR_O_COOK_INS;
1339 }
1340 else if (!strcmp(args[cur_arg], "nocache")) {
1341 curproxy->options |= PR_O_COOK_NOC;
1342 }
1343 else if (!strcmp(args[cur_arg], "postonly")) {
1344 curproxy->options |= PR_O_COOK_POST;
1345 }
1346 else if (!strcmp(args[cur_arg], "prefix")) {
1347 curproxy->options |= PR_O_COOK_PFX;
1348 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001349 else if (!strcmp(args[cur_arg], "domain")) {
1350 if (!*args[cur_arg + 1]) {
1351 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1352 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001355 }
1356
1357 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1358 /* rfc2109, 4.3.2 Rejecting Cookies */
1359 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1360 " dots or does not start with a dot.\n",
1361 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001364 }
1365
1366 err = invalid_domainchar(args[cur_arg + 1]);
1367 if (err) {
1368 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1369 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001372 }
1373
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001374 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001375 cur_arg++;
1376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001378 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 }
1383 cur_arg++;
1384 }
1385 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1386 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001388 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
1390
1391 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1392 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1393 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001394 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 }
1396 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001397 else if (!strcmp(args[0], "persist")) { /* persist */
1398 if (*(args[1]) == 0) {
1399 Alert("parsing [%s:%d] : missing persist method.\n",
1400 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_FATAL;
1402 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001403 }
1404
1405 if (!strncmp(args[1], "rdp-cookie", 10)) {
1406 curproxy->options2 |= PR_O2_RDPC_PRST;
1407
1408 if (*(args[1] + 10 ) == '(') { /* cookie name */
1409 const char *beg, *end;
1410
1411 beg = args[1] + 11;
1412 end = strchr(beg, ')');
1413
1414 if (!end || end == beg) {
1415 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1416 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001417 err_code |= ERR_ALERT | ERR_FATAL;
1418 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001419 }
1420
1421 free(curproxy->rdp_cookie_name);
1422 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1423 curproxy->rdp_cookie_len = end-beg;
1424 }
1425 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1426 free(curproxy->rdp_cookie_name);
1427 curproxy->rdp_cookie_name = strdup("msts");
1428 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1429 }
1430 else { /* syntax */
1431 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001435 }
1436 }
1437 else {
1438 Alert("parsing [%s:%d] : unknown persist method.\n",
1439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001442 }
1443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 if (*(args[5]) == 0) {
1450 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1451 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
1455 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001456 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 curproxy->appsession_name = strdup(args[1]);
1458 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1459 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001460 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1461 if (err) {
1462 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1463 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001464 err_code |= ERR_ALERT | ERR_FATAL;
1465 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001466 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001467 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001468
Willy Tarreau51041c72007-09-09 21:56:53 +02001469 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 }
1474 } /* Url App Session */
1475 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001476 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001477 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480 if (*(args[4]) == 0) {
1481 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001486 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 curproxy->capture_name = strdup(args[2]);
1488 curproxy->capture_namelen = strlen(curproxy->capture_name);
1489 curproxy->capture_len = atol(args[4]);
1490 if (curproxy->capture_len >= CAPTURE_LEN) {
1491 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1492 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001493 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 curproxy->capture_len = CAPTURE_LEN - 1;
1495 }
1496 curproxy->to_log |= LW_COOKIE;
1497 }
1498 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1499 struct cap_hdr *hdr;
1500
1501 if (curproxy == &defproxy) {
1502 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 +02001503 err_code |= ERR_ALERT | ERR_FATAL;
1504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 }
1506
1507 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1508 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1509 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 }
1513
1514 hdr = calloc(sizeof(struct cap_hdr), 1);
1515 hdr->next = curproxy->req_cap;
1516 hdr->name = strdup(args[3]);
1517 hdr->namelen = strlen(args[3]);
1518 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001519 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 hdr->index = curproxy->nb_req_cap++;
1521 curproxy->req_cap = hdr;
1522 curproxy->to_log |= LW_REQHDR;
1523 }
1524 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1525 struct cap_hdr *hdr;
1526
1527 if (curproxy == &defproxy) {
1528 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 +02001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 }
1532
1533 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1534 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1535 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 }
1539 hdr = calloc(sizeof(struct cap_hdr), 1);
1540 hdr->next = curproxy->rsp_cap;
1541 hdr->name = strdup(args[3]);
1542 hdr->namelen = strlen(args[3]);
1543 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001544 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 hdr->index = curproxy->nb_rsp_cap++;
1546 curproxy->rsp_cap = hdr;
1547 curproxy->to_log |= LW_RSPHDR;
1548 }
1549 else {
1550 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001552 err_code |= ERR_ALERT | ERR_FATAL;
1553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 }
1555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001558 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001559
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 if (*(args[1]) == 0) {
1561 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 }
1566 curproxy->conn_retries = atol(args[1]);
1567 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001568 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1569 int pol = ACL_COND_NONE;
1570 struct acl_cond *cond;
1571
Willy Tarreaub099aca2008-10-12 17:26:37 +02001572 if (curproxy == &defproxy) {
1573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001576 }
1577
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001578 if (!strcmp(args[1], "if"))
1579 pol = ACL_COND_IF;
1580 else if (!strcmp(args[1], "unless"))
1581 pol = ACL_COND_UNLESS;
1582
1583 if (pol == ACL_COND_NONE) {
1584 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1585 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
1587 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001588 }
1589
1590 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1591 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001595 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001596 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001597 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001598 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001599 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001600 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001601 else if (!strcmp(args[0], "redirect")) {
1602 int pol = ACL_COND_NONE;
1603 struct acl_cond *cond;
1604 struct redirect_rule *rule;
1605 int cur_arg;
1606 int type = REDIRECT_TYPE_NONE;
1607 int code = 302;
1608 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001609 char *cookie = NULL;
1610 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001611 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001612
1613 cur_arg = 1;
1614 while (*(args[cur_arg])) {
1615 if (!strcmp(args[cur_arg], "location")) {
1616 if (!*args[cur_arg + 1]) {
1617 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1618 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001619 err_code |= ERR_ALERT | ERR_FATAL;
1620 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001621 }
1622
1623 type = REDIRECT_TYPE_LOCATION;
1624 cur_arg++;
1625 destination = args[cur_arg];
1626 }
1627 else if (!strcmp(args[cur_arg], "prefix")) {
1628 if (!*args[cur_arg + 1]) {
1629 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1630 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001633 }
1634
1635 type = REDIRECT_TYPE_PREFIX;
1636 cur_arg++;
1637 destination = args[cur_arg];
1638 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001639 else if (!strcmp(args[cur_arg], "set-cookie")) {
1640 if (!*args[cur_arg + 1]) {
1641 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1642 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001645 }
1646
1647 cur_arg++;
1648 cookie = args[cur_arg];
1649 cookie_set = 1;
1650 }
1651 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1652 if (!*args[cur_arg + 1]) {
1653 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1654 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001657 }
1658
1659 cur_arg++;
1660 cookie = args[cur_arg];
1661 cookie_set = 0;
1662 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001663 else if (!strcmp(args[cur_arg],"code")) {
1664 if (!*args[cur_arg + 1]) {
1665 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1666 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001669 }
1670 cur_arg++;
1671 code = atol(args[cur_arg]);
1672 if (code < 301 || code > 303) {
1673 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1674 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001677 }
1678 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001679 else if (!strcmp(args[cur_arg],"drop-query")) {
1680 flags |= REDIRECT_FLAG_DROP_QS;
1681 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001682 else if (!strcmp(args[cur_arg], "if")) {
1683 pol = ACL_COND_IF;
1684 cur_arg++;
1685 break;
1686 }
1687 else if (!strcmp(args[cur_arg], "unless")) {
1688 pol = ACL_COND_UNLESS;
1689 cur_arg++;
1690 break;
1691 }
1692 else {
1693 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1694 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001697 }
1698 cur_arg++;
1699 }
1700
1701 if (type == REDIRECT_TYPE_NONE) {
1702 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1703 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001706 }
1707
1708 if (pol == ACL_COND_NONE) {
1709 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001713 }
1714
1715 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001716 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001717 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001720 }
1721
Willy Tarreaua9802632008-07-25 19:13:19 +02001722 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001723 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001724 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1725 rule->cond = cond;
1726 rule->rdr_str = strdup(destination);
1727 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001728 if (cookie) {
1729 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1730 * a clear consists in appending "; Max-Age=0" at the end.
1731 */
1732 rule->cookie_len = strlen(cookie);
1733 if (cookie_set)
1734 rule->cookie_str = strdup(cookie);
1735 else {
1736 rule->cookie_str = malloc(rule->cookie_len + 12);
1737 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1738 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1739 rule->cookie_len += 11;
1740 }
1741 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001742 rule->type = type;
1743 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001744 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001745 LIST_INIT(&rule->list);
1746 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001747 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001748 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001749 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001750 int pol = ACL_COND_NONE;
1751 struct acl_cond *cond;
1752 struct switching_rule *rule;
1753
Willy Tarreaub099aca2008-10-12 17:26:37 +02001754 if (curproxy == &defproxy) {
1755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001758 }
1759
Willy Tarreau55ea7572007-06-17 19:56:27 +02001760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001762
1763 if (*(args[1]) == 0) {
1764 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001767 }
1768
1769 if (!strcmp(args[2], "if"))
1770 pol = ACL_COND_IF;
1771 else if (!strcmp(args[2], "unless"))
1772 pol = ACL_COND_UNLESS;
1773
1774 if (pol == ACL_COND_NONE) {
1775 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
1778 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001779 }
1780
1781 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001782 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001783 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001786 }
1787
Willy Tarreaua9802632008-07-25 19:13:19 +02001788 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001789 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001790 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001791 struct acl *acl;
1792 const char *name;
1793
1794 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1795 name = acl ? acl->name : "(unknown)";
1796 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1797 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001798 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001799 }
1800
Willy Tarreau55ea7572007-06-17 19:56:27 +02001801 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1802 rule->cond = cond;
1803 rule->be.name = strdup(args[1]);
1804 LIST_INIT(&rule->list);
1805 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1812 curproxy->uri_auth = NULL; /* we must detach from the default config */
1813
1814 if (*(args[1]) == 0) {
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001815 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable', 'hide-version', 'show-node', 'show-desc'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 } else if (!strcmp(args[1], "uri")) {
1819 if (*(args[2]) == 0) {
1820 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1824 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001825 err_code |= ERR_ALERT | ERR_ABORT;
1826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 }
1828 } else if (!strcmp(args[1], "realm")) {
1829 if (*(args[2]) == 0) {
1830 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1834 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001835 err_code |= ERR_ALERT | ERR_ABORT;
1836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001838 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001839 unsigned interval;
1840
1841 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1842 if (err) {
1843 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1844 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001847 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1848 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001849 err_code |= ERR_ALERT | ERR_ABORT;
1850 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 } else if (!strcmp(args[1], "auth")) {
1853 if (*(args[2]) == 0) {
1854 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1858 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001859 err_code |= ERR_ALERT | ERR_ABORT;
1860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 }
1862 } else if (!strcmp(args[1], "scope")) {
1863 if (*(args[2]) == 0) {
1864 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001867 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1868 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001869 err_code |= ERR_ALERT | ERR_ABORT;
1870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 }
1872 } else if (!strcmp(args[1], "enable")) {
1873 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1874 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_ALERT | ERR_ABORT;
1876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001878 } else if (!strcmp(args[1], "hide-version")) {
1879 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1880 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001881 err_code |= ERR_ALERT | ERR_ABORT;
1882 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001883 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001884 } else if (!strcmp(args[1], "show-node")) {
1885
1886 if (*args[2]) {
1887 int i;
1888 char c;
1889
1890 for (i=0; args[2][i]; i++) {
1891 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02001892 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001893 break;
1894 }
1895
1896 if (!i || args[2][i]) {
1897 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1898 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1899 file, linenum, args[0], args[1]);
1900 err_code |= ERR_ALERT | ERR_FATAL;
1901 goto out;
1902 }
1903 }
1904
1905 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1906 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1907 err_code |= ERR_ALERT | ERR_ABORT;
1908 goto out;
1909 }
1910 } else if (!strcmp(args[1], "show-desc")) {
1911 char *desc = NULL;
1912
1913 if (*args[2]) {
1914 int i, len=0;
1915 char *d;
1916
1917 for(i=2; *args[i]; i++)
1918 len += strlen(args[i])+1;
1919
1920 desc = d = (char *)calloc(1, len);
1921
1922 d += sprintf(d, "%s", args[2]);
1923 for(i=3; *args[i]; i++)
1924 d += sprintf(d, " %s", args[i]);
1925 }
1926
1927 if (!*args[2] && !global.desc)
1928 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1929 file, linenum, args[1]);
1930 else {
1931 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
1932 free(desc);
1933 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1934 err_code |= ERR_ALERT | ERR_ABORT;
1935 goto out;
1936 }
1937 free(desc);
1938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001940 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 }
1945 }
1946 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001947 int optnum;
1948
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001949 if (*(args[1]) == '\0') {
1950 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1951 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001955
1956 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1957 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001958 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1959 err_code |= ERR_WARN;
1960 goto out;
1961 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001962
Willy Tarreau3842f002009-06-14 11:39:52 +02001963 curproxy->no_options &= ~cfg_opts[optnum].val;
1964 curproxy->options &= ~cfg_opts[optnum].val;
1965
1966 switch (kwm) {
1967 case KWM_STD:
1968 curproxy->options |= cfg_opts[optnum].val;
1969 break;
1970 case KWM_NO:
1971 curproxy->no_options |= cfg_opts[optnum].val;
1972 break;
1973 case KWM_DEF: /* already cleared */
1974 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001975 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001976
Willy Tarreau93893792009-07-23 13:19:11 +02001977 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001978 }
1979 }
1980
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001981 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1982 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001983 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1984 err_code |= ERR_WARN;
1985 goto out;
1986 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001987
Willy Tarreau3842f002009-06-14 11:39:52 +02001988 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1989 curproxy->options2 &= ~cfg_opts2[optnum].val;
1990
1991 switch (kwm) {
1992 case KWM_STD:
1993 curproxy->options2 |= cfg_opts2[optnum].val;
1994 break;
1995 case KWM_NO:
1996 curproxy->no_options2 |= cfg_opts2[optnum].val;
1997 break;
1998 case KWM_DEF: /* already cleared */
1999 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002000 }
Willy Tarreau93893792009-07-23 13:19:11 +02002001 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002002 }
2003 }
2004
Willy Tarreau3842f002009-06-14 11:39:52 +02002005 if (kwm != KWM_STD) {
2006 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002007 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002010 }
2011
Emeric Brun3a058f32009-06-30 18:26:00 +02002012 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002014 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002016 if (*(args[2]) != '\0') {
2017 if (!strcmp(args[2], "clf")) {
2018 curproxy->options2 |= PR_O2_CLFLOG;
2019 } else {
2020 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002023 }
2024 }
2025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 else if (!strcmp(args[1], "tcplog"))
2027 /* generate a detailed TCP log */
2028 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 else if (!strcmp(args[1], "tcpka")) {
2030 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002031 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002033
2034 if (curproxy->cap & PR_CAP_FE)
2035 curproxy->options |= PR_O_TCP_CLI_KA;
2036 if (curproxy->cap & PR_CAP_BE)
2037 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
2039 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002040 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_WARN;
2042
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002044 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002045 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002046 curproxy->options &= ~PR_O_SMTP_CHK;
2047 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 if (!*args[2]) { /* no argument */
2049 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2050 curproxy->check_len = strlen(DEF_CHECK_REQ);
2051 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002052 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 curproxy->check_req = (char *)malloc(reqlen);
2054 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2055 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2056 } else { /* more arguments : METHOD URI [HTTP_VER] */
2057 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2058 if (*args[4])
2059 reqlen += strlen(args[4]);
2060 else
2061 reqlen += strlen("HTTP/1.0");
2062
2063 curproxy->check_req = (char *)malloc(reqlen);
2064 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2065 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2066 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002067 }
2068 else if (!strcmp(args[1], "ssl-hello-chk")) {
2069 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002072
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002074 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002075 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002076 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
Willy Tarreau23677902007-05-08 23:50:35 +02002078 else if (!strcmp(args[1], "smtpchk")) {
2079 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002080 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002081 curproxy->options &= ~PR_O_HTTP_CHK;
2082 curproxy->options &= ~PR_O_SSL3_CHK;
2083 curproxy->options |= PR_O_SMTP_CHK;
2084
2085 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2086 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2087 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2088 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2089 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2090 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2091 curproxy->check_req = (char *)malloc(reqlen);
2092 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2093 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2094 } else {
2095 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2096 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2097 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2098 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2099 }
2100 }
2101 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002102 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002103 int cur_arg;
2104
2105 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2106 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002107 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002108
2109 curproxy->options |= PR_O_FWDFOR;
2110
2111 free(curproxy->fwdfor_hdr_name);
2112 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2113 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2114
2115 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2116 cur_arg = 2;
2117 while (*(args[cur_arg])) {
2118 if (!strcmp(args[cur_arg], "except")) {
2119 /* suboption except - needs additional argument for it */
2120 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2121 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2122 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002125 }
2126 /* flush useless bits */
2127 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002128 cur_arg += 2;
2129 } else if (!strcmp(args[cur_arg], "header")) {
2130 /* suboption header - needs additional argument for it */
2131 if (*(args[cur_arg+1]) == 0) {
2132 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2133 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002136 }
2137 free(curproxy->fwdfor_hdr_name);
2138 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2139 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2140 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002141 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002142 /* unknown suboption - catchall */
2143 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002147 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002148 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002149 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002150 else if (!strcmp(args[1], "originalto")) {
2151 int cur_arg;
2152
2153 /* insert x-original-to field, but not for the IP address listed as an except.
2154 * set default options (ie: bitfield, header name, etc)
2155 */
2156
2157 curproxy->options |= PR_O_ORGTO;
2158
2159 free(curproxy->orgto_hdr_name);
2160 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2161 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2162
2163 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2164 cur_arg = 2;
2165 while (*(args[cur_arg])) {
2166 if (!strcmp(args[cur_arg], "except")) {
2167 /* suboption except - needs additional argument for it */
2168 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2169 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2170 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_ALERT | ERR_FATAL;
2172 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002173 }
2174 /* flush useless bits */
2175 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2176 cur_arg += 2;
2177 } else if (!strcmp(args[cur_arg], "header")) {
2178 /* suboption header - needs additional argument for it */
2179 if (*(args[cur_arg+1]) == 0) {
2180 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2181 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002184 }
2185 free(curproxy->orgto_hdr_name);
2186 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2187 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2188 cur_arg += 2;
2189 } else {
2190 /* unknown suboption - catchall */
2191 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2192 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002195 }
2196 } /* end while loop */
2197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 else {
2199 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 }
Willy Tarreau93893792009-07-23 13:19:11 +02002203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002205 else if (!strcmp(args[0], "default_backend")) {
2206 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002208
2209 if (*(args[1]) == 0) {
2210 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002213 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002214 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002215 curproxy->defbe.name = strdup(args[1]);
2216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002221 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 /* enable reconnections to dispatch */
2225 curproxy->options |= PR_O_REDISP;
2226 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002227 else if (!strcmp(args[0], "http-check")) {
2228 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002230
2231 if (strcmp(args[1], "disable-on-404") == 0) {
2232 /* enable a graceful server shutdown on an HTTP 404 response */
2233 curproxy->options |= PR_O_DISABLE404;
2234 }
2235 else {
2236 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002239 }
2240 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002241 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002242 if (curproxy == &defproxy) {
2243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002246 }
2247
Willy Tarreaub80c2302007-11-30 20:51:32 +01002248 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002250
2251 if (strcmp(args[1], "fail") == 0) {
2252 /* add a condition to fail monitor requests */
2253 int pol = ACL_COND_NONE;
2254 struct acl_cond *cond;
2255
2256 if (!strcmp(args[2], "if"))
2257 pol = ACL_COND_IF;
2258 else if (!strcmp(args[2], "unless"))
2259 pol = ACL_COND_UNLESS;
2260
2261 if (pol == ACL_COND_NONE) {
2262 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2263 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002266 }
2267
2268 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2269 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2270 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002273 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002274 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002275 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002276 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2277 }
2278 else {
2279 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002282 }
2283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284#ifdef TPROXY
2285 else if (!strcmp(args[0], "transparent")) {
2286 /* enable transparent proxy connections */
2287 curproxy->options |= PR_O_TRANSP;
2288 }
2289#endif
2290 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 if (*(args[1]) == 0) {
2295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_FATAL;
2297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 }
2299 curproxy->maxconn = atol(args[1]);
2300 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002301 else if (!strcmp(args[0], "backlog")) { /* backlog */
2302 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002304
2305 if (*(args[1]) == 0) {
2306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
2308 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002309 }
2310 curproxy->backlog = atol(args[1]);
2311 }
Willy Tarreau86034312006-12-29 00:10:33 +01002312 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002314 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002315
Willy Tarreau86034312006-12-29 00:10:33 +01002316 if (*(args[1]) == 0) {
2317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002320 }
2321 curproxy->fullconn = atol(args[1]);
2322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2324 if (*(args[1]) == 0) {
2325 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002329 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2330 if (err) {
2331 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2332 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002335 }
2336 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 }
2338 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2339 if (curproxy == &defproxy) {
2340 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002344 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002346
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 if (strchr(args[1], ':') == NULL) {
2348 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
2352 curproxy->dispatch_addr = *str2sa(args[1]);
2353 }
2354 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002355 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002358 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002359 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2360 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365 else if (!strcmp(args[0], "server")) { /* server address */
2366 int cur_arg;
2367 char *rport;
2368 char *raddr;
2369 short realport;
2370 int do_check;
2371
2372 if (curproxy == &defproxy) {
2373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002377 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379
2380 if (!*args[2]) {
2381 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2382 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002386
2387 err = invalid_char(args[1]);
2388 if (err) {
2389 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2390 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002393 }
2394
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2396 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_ABORT;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400
2401 /* the servers are linked backwards first */
2402 newsrv->next = curproxy->srv;
2403 curproxy->srv = newsrv;
2404 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002405 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406
2407 LIST_INIT(&newsrv->pendconns);
2408 do_check = 0;
2409 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002410 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 newsrv->id = strdup(args[1]);
2412
2413 /* several ways to check the port component :
2414 * - IP => port=+0, relative
2415 * - IP: => port=+0, relative
2416 * - IP:N => port=N, absolute
2417 * - IP:+N => port=+N, relative
2418 * - IP:-N => port=-N, relative
2419 */
2420 raddr = strdup(args[2]);
2421 rport = strchr(raddr, ':');
2422 if (rport) {
2423 *rport++ = 0;
2424 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002425 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 newsrv->state |= SRV_MAPPORTS;
2427 } else {
2428 realport = 0;
2429 newsrv->state |= SRV_MAPPORTS;
2430 }
2431
2432 newsrv->addr = *str2sa(raddr);
2433 newsrv->addr.sin_port = htons(realport);
2434 free(raddr);
2435
2436 newsrv->curfd = -1; /* no health-check in progress */
2437 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002438 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2439 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 newsrv->rise = DEF_RISETIME;
2441 newsrv->fall = DEF_FALLTIME;
2442 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002443 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002444 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002445 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002446
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 cur_arg = 3;
2448 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002449 if (!strcmp(args[cur_arg], "id")) {
2450 struct server *target;
2451
2452 if (!*args[cur_arg + 1]) {
2453 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2454 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002457 }
2458
2459 newsrv->puid = atol(args[cur_arg + 1]);
2460
2461 if (newsrv->puid< 1001) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002462 Alert("parsing [%s:%d]: custom id has to be > 1000.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002463 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002466 }
2467
2468 for (target = proxy->srv; target; target = target->next)
2469 if (newsrv != target && newsrv->puid == target->puid) {
2470 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2471 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002474 }
2475 cur_arg += 2;
2476 }
2477 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 newsrv->cookie = strdup(args[cur_arg + 1]);
2479 newsrv->cklen = strlen(args[cur_arg + 1]);
2480 cur_arg += 2;
2481 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002482 else if (!strcmp(args[cur_arg], "redir")) {
2483 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2484 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2485 cur_arg += 2;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002488 if (!*args[cur_arg + 1]) {
2489 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2490 file, linenum, args[cur_arg]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002496 if (newsrv->rise <= 0) {
2497 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2498 file, linenum, args[cur_arg]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 newsrv->health = newsrv->rise;
2504 cur_arg += 2;
2505 }
2506 else if (!strcmp(args[cur_arg], "fall")) {
2507 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02002508
2509 if (!*args[cur_arg + 1]) {
2510 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2511 file, linenum, args[cur_arg]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515
2516 if (newsrv->fall <= 0) {
2517 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
2518 file, linenum, args[cur_arg]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 cur_arg += 2;
2524 }
2525 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002526 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2527 if (err) {
2528 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2529 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002532 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002533 if (val <= 0) {
2534 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2535 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002538 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002539 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 cur_arg += 2;
2541 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002542 else if (!strcmp(args[cur_arg], "fastinter")) {
2543 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2544 if (err) {
2545 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2546 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002549 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002550 if (val <= 0) {
2551 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2552 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002555 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002556 newsrv->fastinter = val;
2557 cur_arg += 2;
2558 }
2559 else if (!strcmp(args[cur_arg], "downinter")) {
2560 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2561 if (err) {
2562 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2563 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002566 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002567 if (val <= 0) {
2568 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2569 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002572 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002573 newsrv->downinter = val;
2574 cur_arg += 2;
2575 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002576 else if (!strcmp(args[cur_arg], "addr")) {
2577 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002578 cur_arg += 2;
2579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 else if (!strcmp(args[cur_arg], "port")) {
2581 newsrv->check_port = atol(args[cur_arg + 1]);
2582 cur_arg += 2;
2583 }
2584 else if (!strcmp(args[cur_arg], "backup")) {
2585 newsrv->state |= SRV_BACKUP;
2586 cur_arg ++;
2587 }
2588 else if (!strcmp(args[cur_arg], "weight")) {
2589 int w;
2590 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002591 if (w < 0 || w > 256) {
2592 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002597 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 cur_arg += 2;
2599 }
2600 else if (!strcmp(args[cur_arg], "minconn")) {
2601 newsrv->minconn = atol(args[cur_arg + 1]);
2602 cur_arg += 2;
2603 }
2604 else if (!strcmp(args[cur_arg], "maxconn")) {
2605 newsrv->maxconn = atol(args[cur_arg + 1]);
2606 cur_arg += 2;
2607 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002608 else if (!strcmp(args[cur_arg], "maxqueue")) {
2609 newsrv->maxqueue = atol(args[cur_arg + 1]);
2610 cur_arg += 2;
2611 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002612 else if (!strcmp(args[cur_arg], "slowstart")) {
2613 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002614 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002615 if (err) {
2616 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2617 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002620 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002621 if (val <= 0) {
2622 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2623 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002626 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002627 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002628 cur_arg += 2;
2629 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002630 else if (!strcmp(args[cur_arg], "track")) {
2631
2632 if (!*args[cur_arg + 1]) {
2633 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2634 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002637 }
2638
2639 newsrv->trackit = strdup(args[cur_arg + 1]);
2640
2641 cur_arg += 2;
2642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 else if (!strcmp(args[cur_arg], "check")) {
2644 global.maxsock++;
2645 do_check = 1;
2646 cur_arg += 1;
2647 }
2648 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002649 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002651#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002652 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002653 file, linenum, "source", "usesrc");
2654#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002655 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002657#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 }
2661 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002662 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2663
2664 if (port_low != port_high) {
2665 int i;
2666 if (port_low <= 0 || port_low > 65535 ||
2667 port_high <= 0 || port_high > 65535 ||
2668 port_low > port_high) {
2669 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2670 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002673 }
2674 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2675 for (i = 0; i < newsrv->sport_range->size; i++)
2676 newsrv->sport_range->ports[i] = port_low + i;
2677 }
2678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002680 while (*(args[cur_arg])) {
2681 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002682#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2683#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002684 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2685 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2686 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002689 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002690#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002691 if (!*args[cur_arg + 1]) {
2692 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2693 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002696 }
2697 if (!strcmp(args[cur_arg + 1], "client")) {
2698 newsrv->state |= SRV_TPROXY_CLI;
2699 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2700 newsrv->state |= SRV_TPROXY_CIP;
2701 } else {
2702 newsrv->state |= SRV_TPROXY_ADDR;
2703 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2704 }
2705 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002706#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002707 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002708#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002709 cur_arg += 2;
2710 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002711#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002712 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002713 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002716#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2717 } /* "usesrc" */
2718
2719 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2720#ifdef SO_BINDTODEVICE
2721 if (!*args[cur_arg + 1]) {
2722 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2723 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002726 }
2727 if (newsrv->iface_name)
2728 free(newsrv->iface_name);
2729
2730 newsrv->iface_name = strdup(args[cur_arg + 1]);
2731 newsrv->iface_len = strlen(newsrv->iface_name);
2732 global.last_checks |= LSTCHK_NETADM;
2733#else
2734 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2735 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002738#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002739 cur_arg += 2;
2740 continue;
2741 }
2742 /* this keyword in not an option of "source" */
2743 break;
2744 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002746 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2747 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2748 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002753 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758 }
2759
2760 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002761 if (newsrv->trackit) {
2762 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2763 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002766 }
2767
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002768 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2769 newsrv->check_port = newsrv->check_addr.sin_port;
2770
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2772 newsrv->check_port = realport; /* by default */
2773 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002774 /* not yet valid, because no port was set on
2775 * the server either. We'll check if we have
2776 * a known port on the first listener.
2777 */
2778 struct listener *l;
2779 l = curproxy->listen;
2780 if (l) {
2781 int port;
2782 port = (l->addr.ss_family == AF_INET6)
2783 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2784 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2785 newsrv->check_port = port;
2786 }
2787 }
2788 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002789 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2790 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02002794
2795 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 newsrv->state |= SRV_CHECKED;
2797 }
2798
2799 if (newsrv->state & SRV_BACKUP)
2800 curproxy->srv_bck++;
2801 else
2802 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002803
2804 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 }
2806 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002807 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 int facility;
2809
2810 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2811 curproxy->logfac1 = global.logfac1;
2812 curproxy->logsrv1 = global.logsrv1;
2813 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002814 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 curproxy->logfac2 = global.logfac2;
2816 curproxy->logsrv2 = global.logsrv2;
2817 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002818 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 }
2820 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002821 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822
2823 facility = get_log_facility(args[2]);
2824 if (facility < 0) {
2825 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2826 exit(1);
2827 }
2828
2829 level = 7; /* max syslog level = debug */
2830 if (*(args[3])) {
2831 level = get_log_level(args[3]);
2832 if (level < 0) {
2833 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2834 exit(1);
2835 }
2836 }
2837
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002838 minlvl = 0; /* limit syslog level to this level (emerg) */
2839 if (*(args[4])) {
2840 minlvl = get_log_level(args[4]);
2841 if (level < 0) {
2842 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2843 exit(1);
2844 }
2845 }
2846
Robert Tsai81ae1952007-12-05 10:47:29 +01002847 if (args[1][0] == '/') {
2848 logsrv.u.addr.sa_family = AF_UNIX;
2849 logsrv.u.un = *str2sun(args[1]);
2850 } else {
2851 logsrv.u.addr.sa_family = AF_INET;
2852 logsrv.u.in = *str2sa(args[1]);
2853 if (!logsrv.u.in.sin_port) {
2854 logsrv.u.in.sin_port =
2855 htons(SYSLOG_PORT);
2856 }
2857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858
2859 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002860 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 curproxy->logfac1 = facility;
2862 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002863 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 }
2865 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002866 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 curproxy->logfac2 = facility;
2868 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002869 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
2871 else {
2872 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002875 }
2876 }
2877 else {
2878 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2879 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
2883 }
2884 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002885 int cur_arg;
2886
Willy Tarreau977b8e42006-12-29 14:19:17 +01002887 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002891 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2892 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002896
2897 /* we must first clear any optional default setting */
2898 curproxy->options &= ~PR_O_TPXY_MASK;
2899 free(curproxy->iface_name);
2900 curproxy->iface_name = NULL;
2901 curproxy->iface_len = 0;
2902
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 curproxy->source_addr = *str2sa(args[1]);
2904 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002905
2906 cur_arg = 2;
2907 while (*(args[cur_arg])) {
2908 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002909#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2910#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002911 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2912 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2913 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002916 }
2917#endif
2918 if (!*args[cur_arg + 1]) {
2919 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2920 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002923 }
2924
2925 if (!strcmp(args[cur_arg + 1], "client")) {
2926 curproxy->options |= PR_O_TPXY_CLI;
2927 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2928 curproxy->options |= PR_O_TPXY_CIP;
2929 } else {
2930 curproxy->options |= PR_O_TPXY_ADDR;
2931 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2932 }
2933 global.last_checks |= LSTCHK_NETADM;
2934#if !defined(CONFIG_HAP_LINUX_TPROXY)
2935 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002936#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002937#else /* no TPROXY support */
2938 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002939 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002942#endif
2943 cur_arg += 2;
2944 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002945 }
2946
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002947 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2948#ifdef SO_BINDTODEVICE
2949 if (!*args[cur_arg + 1]) {
2950 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2951 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002954 }
2955 if (curproxy->iface_name)
2956 free(curproxy->iface_name);
2957
2958 curproxy->iface_name = strdup(args[cur_arg + 1]);
2959 curproxy->iface_len = strlen(curproxy->iface_name);
2960 global.last_checks |= LSTCHK_NETADM;
2961#else
2962 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2963 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002966#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002967 cur_arg += 2;
2968 continue;
2969 }
2970 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2971 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002976 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2977 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2978 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002982 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2983 regex_t *preg;
2984 if (curproxy == &defproxy) {
2985 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002988 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002991
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 if (*(args[1]) == 0 || *(args[2]) == 0) {
2993 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2994 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 }
2998
2999 preg = calloc(1, sizeof(regex_t));
3000 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3001 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
3005
3006 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3007 if (err) {
3008 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3009 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003012 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
3014 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3015 regex_t *preg;
3016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003021 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 if (*(args[1]) == 0) {
3025 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 }
3029
3030 preg = calloc(1, sizeof(regex_t));
3031 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3032 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035 }
3036
3037 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003038 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 }
3040 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3041 regex_t *preg;
3042 if (curproxy == &defproxy) {
3043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (*(args[1]) == 0) {
3051 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
3055
3056 preg = calloc(1, sizeof(regex_t));
3057 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3058 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
3062
3063 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003064 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 }
3066 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3067 regex_t *preg;
3068 if (curproxy == &defproxy) {
3069 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003074 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003075
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 if (*(args[1]) == 0) {
3077 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
3081
3082 preg = calloc(1, sizeof(regex_t));
3083 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3084 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
3088
3089 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003090 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 }
3092 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3093 regex_t *preg;
3094 if (curproxy == &defproxy) {
3095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003099 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003101
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 if (*(args[1]) == 0) {
3103 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 }
3107
3108 preg = calloc(1, sizeof(regex_t));
3109 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3110 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 }
3114
3115 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003116 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003118 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3119 regex_t *preg;
3120 if (curproxy == &defproxy) {
3121 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003124 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003125 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003127
Willy Tarreaub8750a82006-09-03 09:56:00 +02003128 if (*(args[1]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003132 }
3133
3134 preg = calloc(1, sizeof(regex_t));
3135 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3136 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003139 }
3140
3141 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003142 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003143 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003144 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3145 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003146 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003147 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003151 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003153
Willy Tarreau977b8e42006-12-29 14:19:17 +01003154 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003155 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3156 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003159 }
3160
3161 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003162 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003163 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003166 }
3167
3168 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003169 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003170 }
3171 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3172 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003173 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003174 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003177 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003178 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003180
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003182 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003186 }
3187
3188 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003189 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003190 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003193 }
3194
3195 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003196 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3199 regex_t *preg;
3200 if (curproxy == &defproxy) {
3201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003205 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003207
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 if (*(args[1]) == 0 || *(args[2]) == 0) {
3209 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3210 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214
3215 preg = calloc(1, sizeof(regex_t));
3216 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3217 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
3221
3222 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3223 if (err) {
3224 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3225 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003229 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 }
3231 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3232 regex_t *preg;
3233 if (curproxy == &defproxy) {
3234 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003238 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 if (*(args[1]) == 0) {
3242 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
3246
3247 preg = calloc(1, sizeof(regex_t));
3248 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3249 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
3253
3254 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003255 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
3257 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3258 regex_t *preg;
3259 if (curproxy == &defproxy) {
3260 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003264 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003266
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 if (*(args[1]) == 0) {
3268 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
3272
3273 preg = calloc(1, sizeof(regex_t));
3274 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3275 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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
3280 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003281 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3284 regex_t *preg;
3285 if (curproxy == &defproxy) {
3286 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003290 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003291 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003292
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 if (*(args[1]) == 0) {
3294 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 }
3298
3299 preg = calloc(1, sizeof(regex_t));
3300 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3301 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
3305
3306 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003307 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
3309 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3310 regex_t *preg;
3311 if (curproxy == &defproxy) {
3312 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003316 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003318
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 if (*(args[1]) == 0) {
3320 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
3324
3325 preg = calloc(1, sizeof(regex_t));
3326 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3327 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331
3332 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003333 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003335 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3336 regex_t *preg;
3337 if (curproxy == &defproxy) {
3338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003341 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003342 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003343 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003344
Willy Tarreaub8750a82006-09-03 09:56:00 +02003345 if (*(args[1]) == 0) {
3346 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003349 }
3350
3351 preg = calloc(1, sizeof(regex_t));
3352 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3353 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003356 }
3357
3358 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003359 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3362 if (curproxy == &defproxy) {
3363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003367 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369
3370 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3371 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
3375
3376 if (*(args[1]) == 0) {
3377 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
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 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003383 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
3385 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3386 regex_t *preg;
3387
3388 if (*(args[1]) == 0 || *(args[2]) == 0) {
3389 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003394 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003396
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 preg = calloc(1, sizeof(regex_t));
3398 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3399 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403
3404 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3405 if (err) {
3406 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3407 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003411 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3414 regex_t *preg;
3415 if (curproxy == &defproxy) {
3416 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003420 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003422
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 if (*(args[1]) == 0) {
3424 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003425 err_code |= ERR_ALERT | ERR_FATAL;
3426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428
3429 preg = calloc(1, sizeof(regex_t));
3430 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3431 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_FATAL;
3433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
3435
3436 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3437 if (err) {
3438 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3439 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443 }
3444 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3445 regex_t *preg;
3446 if (curproxy == &defproxy) {
3447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003451 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003452 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003453
Willy Tarreaubaaee002006-06-26 02:48:02 +02003454 if (*(args[1]) == 0) {
3455 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003456 err_code |= ERR_ALERT | ERR_FATAL;
3457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 }
3459
3460 preg = calloc(1, sizeof(regex_t));
3461 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3462 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 }
3466
3467 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3468 if (err) {
3469 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3470 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 }
3474 }
3475 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3476 regex_t *preg;
3477 if (curproxy == &defproxy) {
3478 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003482 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484
3485 if (*(args[1]) == 0 || *(args[2]) == 0) {
3486 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3487 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 }
3491
3492 preg = calloc(1, sizeof(regex_t));
3493 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3494 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 }
3498
3499 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3500 if (err) {
3501 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3502 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 }
3506 }
3507 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3508 regex_t *preg;
3509 if (curproxy == &defproxy) {
3510 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003514 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003516
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 if (*(args[1]) == 0) {
3518 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
3522
3523 preg = calloc(1, sizeof(regex_t));
3524 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3525 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 }
3529
3530 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3531 if (err) {
3532 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3533 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537 }
3538 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3539 regex_t *preg;
3540 if (curproxy == &defproxy) {
3541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003545 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003547
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 if (*(args[1]) == 0) {
3549 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
3553
3554 preg = calloc(1, sizeof(regex_t));
3555 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3556 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
3560
3561 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3562 if (err) {
3563 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3564 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 }
3568 }
3569 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3570 if (curproxy == &defproxy) {
3571 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003575 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003576 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577
3578 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3579 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
3583
3584 if (*(args[1]) == 0) {
3585 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
3589
3590 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3591 }
3592 else if (!strcmp(args[0], "errorloc") ||
3593 !strcmp(args[0], "errorloc302") ||
3594 !strcmp(args[0], "errorloc303")) { /* error location */
3595 int errnum, errlen;
3596 char *err;
3597
Willy Tarreau977b8e42006-12-29 14:19:17 +01003598 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003600
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003602 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606
3607 errnum = atol(args[1]);
3608 if (!strcmp(args[0], "errorloc303")) {
3609 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3610 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3611 } else {
3612 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3613 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3614 }
3615
Willy Tarreau0f772532006-12-23 20:51:41 +01003616 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3617 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003618 chunk_destroy(&curproxy->errmsg[rc]);
3619 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01003620 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003623
3624 if (rc >= HTTP_ERR_SIZE) {
3625 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3626 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 free(err);
3628 }
3629 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003630 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3631 int errnum, errlen, fd;
3632 char *err;
3633 struct stat stat;
3634
3635 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003637
3638 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003639 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003642 }
3643
3644 fd = open(args[2], O_RDONLY);
3645 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3646 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3647 file, linenum, args[2], args[1]);
3648 if (fd >= 0)
3649 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003652 }
3653
Willy Tarreau27a674e2009-08-17 07:23:33 +02003654 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003655 errlen = stat.st_size;
3656 } else {
3657 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003658 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003660 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003661 }
3662
3663 err = malloc(errlen); /* malloc() must succeed during parsing */
3664 errnum = read(fd, err, errlen);
3665 if (errnum != errlen) {
3666 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3667 file, linenum, args[2], args[1]);
3668 close(fd);
3669 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003672 }
3673 close(fd);
3674
3675 errnum = atol(args[1]);
3676 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3677 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003678 chunk_destroy(&curproxy->errmsg[rc]);
3679 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003680 break;
3681 }
3682 }
3683
3684 if (rc >= HTTP_ERR_SIZE) {
3685 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3686 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003688 free(err);
3689 }
3690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003692 struct cfg_kw_list *kwl;
3693 int index;
3694
3695 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3696 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3697 if (kwl->kw[index].section != CFG_LISTEN)
3698 continue;
3699 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3700 /* prepare error message just in case */
3701 snprintf(trash, sizeof(trash),
3702 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003703 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3704 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003705 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003708 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003709 else if (rc > 0) {
3710 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_WARN;
3712 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003713 }
Willy Tarreau93893792009-07-23 13:19:11 +02003714 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003715 }
3716 }
3717 }
3718
Willy Tarreau6daf3432008-01-22 16:44:08 +01003719 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
Willy Tarreau93893792009-07-23 13:19:11 +02003723 out:
3724 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725}
3726
3727
3728/*
3729 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003730 * Returns the error code, 0 if OK, or any combination of :
3731 * - ERR_ABORT: must abort ASAP
3732 * - ERR_FATAL: we can continue parsing but not start the service
3733 * - ERR_WARN: a warning has been emitted
3734 * - ERR_ALERT: an alert has been emitted
3735 * Only the two first ones can stop processing, the two others are just
3736 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003738int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003740 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 FILE *f;
3742 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003744 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 if ((f=fopen(file,"r")) == NULL)
3747 return -1;
3748
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003749 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003750 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003751 char *end;
3752 char *args[MAX_LINE_ARGS + 1];
3753 char *line = thisline;
3754
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755 linenum++;
3756
3757 end = line + strlen(line);
3758
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003759 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3760 /* Check if we reached the limit and the last char is not \n.
3761 * Watch out for the last line without the terminating '\n'!
3762 */
3763 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003764 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003766 }
3767
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003769 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 line++;
3771
3772 arg = 0;
3773 args[arg] = line;
3774
3775 while (*line && arg < MAX_LINE_ARGS) {
3776 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3777 * C equivalent value. Other combinations left unchanged (eg: \1).
3778 */
3779 if (*line == '\\') {
3780 int skip = 0;
3781 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3782 *line = line[1];
3783 skip = 1;
3784 }
3785 else if (line[1] == 'r') {
3786 *line = '\r';
3787 skip = 1;
3788 }
3789 else if (line[1] == 'n') {
3790 *line = '\n';
3791 skip = 1;
3792 }
3793 else if (line[1] == 't') {
3794 *line = '\t';
3795 skip = 1;
3796 }
3797 else if (line[1] == 'x') {
3798 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3799 unsigned char hex1, hex2;
3800 hex1 = toupper(line[2]) - '0';
3801 hex2 = toupper(line[3]) - '0';
3802 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3803 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3804 *line = (hex1<<4) + hex2;
3805 skip = 3;
3806 }
3807 else {
3808 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
3811 }
3812 if (skip) {
3813 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3814 end -= skip;
3815 }
3816 line++;
3817 }
3818 else if (*line == '#' || *line == '\n' || *line == '\r') {
3819 /* end of string, end of loop */
3820 *line = 0;
3821 break;
3822 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003823 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003825 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003826 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 line++;
3828 args[++arg] = line;
3829 }
3830 else {
3831 line++;
3832 }
3833 }
3834
3835 /* empty line */
3836 if (!**args)
3837 continue;
3838
Willy Tarreau540abe42007-05-02 20:50:16 +02003839 /* zero out remaining args and ensure that at least one entry
3840 * is zeroed out.
3841 */
3842 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 args[arg] = line;
3844 }
3845
Willy Tarreau3842f002009-06-14 11:39:52 +02003846 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003847 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003848 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003849 for (arg=0; *args[arg+1]; arg++)
3850 args[arg] = args[arg+1]; // shift args after inversion
3851 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003852 else if (!strcmp(args[0], "default")) {
3853 kwm = KWM_DEF;
3854 for (arg=0; *args[arg+1]; arg++)
3855 args[arg] = args[arg+1]; // shift args after inversion
3856 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003857
Willy Tarreau3842f002009-06-14 11:39:52 +02003858 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3859 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003861 }
3862
Willy Tarreau977b8e42006-12-29 14:19:17 +01003863 if (!strcmp(args[0], "listen") ||
3864 !strcmp(args[0], "frontend") ||
3865 !strcmp(args[0], "backend") ||
3866 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003867 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003869 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003870 cursection = strdup(args[0]);
3871 }
3872 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003874 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003875 cursection = strdup(args[0]);
3876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 /* else it's a section keyword */
3878
3879 switch (confsect) {
3880 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 break;
3883 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003884 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 break;
3886 default:
3887 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003890
3891 if (err_code & ERR_ABORT)
3892 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003894 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003895 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003897 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003898}
3899
Willy Tarreaubb925012009-07-23 13:36:36 +02003900/*
3901 * Returns the error code, 0 if OK, or any combination of :
3902 * - ERR_ABORT: must abort ASAP
3903 * - ERR_FATAL: we can continue parsing but not start the service
3904 * - ERR_WARN: a warning has been emitted
3905 * - ERR_ALERT: an alert has been emitted
3906 * Only the two first ones can stop processing, the two others are just
3907 * indicators.
3908 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003909int check_config_validity()
3910{
3911 int cfgerr = 0;
3912 struct proxy *curproxy = NULL;
3913 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003914 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915
3916 /*
3917 * Now, check for the integrity of all that we have collected.
3918 */
3919
3920 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003921 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003923 /* first, we will invert the proxy list order */
3924 curproxy = NULL;
3925 while (proxy) {
3926 struct proxy *next;
3927
3928 next = proxy->next;
3929 proxy->next = curproxy;
3930 curproxy = proxy;
3931 if (!next)
3932 break;
3933 proxy = next;
3934 }
3935
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003937 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
3941
3942 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003943 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003944 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003945
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003947 /* ensure we don't keep listeners uselessly bound */
3948 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 curproxy = curproxy->next;
3950 continue;
3951 }
3952
Willy Tarreauff01a212009-03-15 13:46:16 +01003953 switch (curproxy->mode) {
3954 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003955 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003956 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003957 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3958 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003959 cfgerr++;
3960 }
3961
3962 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003963 Warning("config : servers will be ignored for %s '%s'.\n",
3964 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003965 break;
3966
3967 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003968 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003969 break;
3970
3971 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003972 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003973 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003974 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3975 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003976 cfgerr++;
3977 }
3978 break;
3979 }
3980
3981 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003982 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3983 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 cfgerr++;
3985 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003986
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003987 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02003988 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003989 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003990 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
3991 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003992 cfgerr++;
3993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003995 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003996 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3997 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003998 cfgerr++;
3999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004001 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004002 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4003 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004004 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004005 }
4006 }
4007 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4008 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4009 /* If no LB algo is set in a backend, and we're not in
4010 * transparent mode, dispatch mode nor proxy mode, we
4011 * want to use balance roundrobin by default.
4012 */
4013 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4014 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 }
4016 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004017
Willy Tarreau82936582007-11-30 15:20:09 +01004018 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4019 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004020 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4021 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004022 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004023 }
4024
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004025 /* if a default backend was specified, let's find it */
4026 if (curproxy->defbe.name) {
4027 struct proxy *target;
4028
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004029 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
4030 if (!target) {
4031 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4032 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004033 cfgerr++;
4034 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004035 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4036 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004037 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004038 } else {
4039 free(curproxy->defbe.name);
4040 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004041 /* we force the backend to be present on at least all of
4042 * the frontend's processes.
4043 */
4044 target->bind_proc = curproxy->bind_proc ?
4045 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
4047 }
4048
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004049 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004050 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4051 /* map jump target for ACT_SETBE in req_rep chain */
4052 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004053 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004054 struct proxy *target;
4055
Willy Tarreaua496b602006-12-17 23:15:24 +01004056 if (exp->action != ACT_SETBE)
4057 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004058
4059 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
4060 if (!target) {
4061 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4062 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004063 cfgerr++;
4064 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004065 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4066 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004067 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004068 } else {
4069 free((void *)exp->replace);
4070 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004071 /* we force the backend to be present on at least all of
4072 * the frontend's processes.
4073 */
4074 target->bind_proc = curproxy->bind_proc ?
4075 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004076 }
4077 }
4078 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004079
4080 /* find the target proxy for 'use_backend' rules */
4081 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004082 struct proxy *target;
4083
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004084 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004085
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004086 if (!target) {
4087 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4088 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004089 cfgerr++;
4090 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004091 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4092 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004093 cfgerr++;
4094 } else {
4095 free((void *)rule->be.name);
4096 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004097 /* we force the backend to be present on at least all of
4098 * the frontend's processes.
4099 */
4100 target->bind_proc = curproxy->bind_proc ?
4101 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004102 }
4103 }
4104
Willy Tarreau2738a142006-07-08 17:28:09 +02004105 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004106 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004107 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004108 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004109 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004110 " | While not properly invalid, you will certainly encounter various problems\n"
4111 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004112 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004113 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004114 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004115 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004116
Willy Tarreau1fa31262007-12-03 00:36:16 +01004117 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4118 * We must still support older configurations, so let's find out whether those
4119 * parameters have been set or must be copied from contimeouts.
4120 */
4121 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004122 if (!curproxy->timeout.tarpit ||
4123 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004124 /* tarpit timeout not set. We search in the following order:
4125 * default.tarpit, curr.connect, default.connect.
4126 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004127 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004128 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004129 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004130 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004131 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004132 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004133 }
4134 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004135 (!curproxy->timeout.queue ||
4136 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004137 /* queue timeout not set. We search in the following order:
4138 * default.queue, curr.connect, default.connect.
4139 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004140 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004141 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004142 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004143 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004144 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004145 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004146 }
4147 }
4148
Willy Tarreauf3c69202006-07-09 16:42:34 +02004149 if (curproxy->options & PR_O_SSL3_CHK) {
4150 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4151 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4152 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4153 }
4154
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004155 /* The small pools required for the capture lists */
4156 if (curproxy->nb_req_cap)
4157 curproxy->req_cap_pool = create_pool("ptrcap",
4158 curproxy->nb_req_cap * sizeof(char *),
4159 MEM_F_SHARED);
4160 if (curproxy->nb_rsp_cap)
4161 curproxy->rsp_cap_pool = create_pool("ptrcap",
4162 curproxy->nb_rsp_cap * sizeof(char *),
4163 MEM_F_SHARED);
4164
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004165 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4166 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4167 MEM_F_SHARED);
4168
Willy Tarreau86034312006-12-29 00:10:33 +01004169 /* for backwards compatibility with "listen" instances, if
4170 * fullconn is not set but maxconn is set, then maxconn
4171 * is used.
4172 */
4173 if (!curproxy->fullconn)
4174 curproxy->fullconn = curproxy->maxconn;
4175
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 /* first, we will invert the servers list order */
4177 newsrv = NULL;
4178 while (curproxy->srv) {
4179 struct server *next;
4180
4181 next = curproxy->srv->next;
4182 curproxy->srv->next = newsrv;
4183 newsrv = curproxy->srv;
4184 if (!next)
4185 break;
4186 curproxy->srv = next;
4187 }
4188
Willy Tarreau20697042007-11-15 23:26:18 +01004189 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004190 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004191
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004192 /* We have to initialize the server lookup mechanism depending
4193 * on what LB algorithm was choosen.
4194 */
4195
4196 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4197 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4198 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004199 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4200 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4201 init_server_map(curproxy);
4202 } else {
4203 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4204 fwrr_init_server_groups(curproxy);
4205 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004206 break;
4207 case BE_LB_KIND_LC:
4208 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004209 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004210 break;
4211 case BE_LB_KIND_HI:
4212 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
Willy Tarreaub625a082007-11-26 01:15:43 +01004213 init_server_map(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004214 break;
4215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216
4217 if (curproxy->options & PR_O_LOGASAP)
4218 curproxy->to_log &= ~LW_BYTES;
4219
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004220 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4221 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4222 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4223 proxy_type_str(curproxy), curproxy->id);
4224 err_code |= ERR_WARN;
4225 }
4226
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004228 * ensure that we're not cross-dressing a TCP server into HTTP.
4229 */
4230 newsrv = curproxy->srv;
4231 while (newsrv != NULL) {
4232 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004233 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4234 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004235 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004236 }
4237 newsrv = newsrv->next;
4238 }
4239
4240 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 * If this server supports a maxconn parameter, it needs a dedicated
4242 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004243 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 */
4245 newsrv = curproxy->srv;
4246 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004247 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 /* Only 'minconn' was specified, or it was higher than or equal
4249 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4250 * this will avoid further useless expensive computations.
4251 */
4252 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004253 } else if (newsrv->maxconn && !newsrv->minconn) {
4254 /* minconn was not specified, so we set it to maxconn */
4255 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004256 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004257 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4258 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004259 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 }
4261
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004262 if (newsrv->trackit) {
4263 struct proxy *px;
4264 struct server *srv;
4265 char *pname, *sname;
4266
4267 pname = newsrv->trackit;
4268 sname = strrchr(pname, '/');
4269
4270 if (sname)
4271 *sname++ = '\0';
4272 else {
4273 sname = pname;
4274 pname = NULL;
4275 }
4276
4277 if (pname) {
4278 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4279 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004280 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4281 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004282 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004283 cfgerr++;
4284 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004285 }
4286 } else
4287 px = curproxy;
4288
4289 srv = findserver(px, sname);
4290 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004291 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4292 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004293 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004294 cfgerr++;
4295 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004296 }
4297
4298 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004299 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004300 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004301 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004302 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004303 cfgerr++;
4304 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004305 }
4306
4307 if (curproxy != px &&
4308 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004309 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004310 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004311 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004312 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004313 cfgerr++;
4314 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004315 }
4316
4317 newsrv->tracked = srv;
4318 newsrv->tracknext = srv->tracknext;
4319 srv->tracknext = newsrv;
4320
4321 free(newsrv->trackit);
4322 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004323 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 newsrv = newsrv->next;
4325 }
4326
Willy Tarreauc1a21672009-08-16 22:37:44 +02004327 if (curproxy->cap & PR_CAP_FE) {
4328 if (curproxy->tcp_req.inspect_delay ||
4329 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4330 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4331
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004332 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004333 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004334 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4335 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004336
4337 /* both TCP and HTTP must check switching rules */
4338 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4339 }
4340
4341 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004342 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004343 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004344 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4345 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004346
4347 /* If the backend does requires RDP cookie persistence, we have to
4348 * enable the corresponding analyser.
4349 */
4350 if (curproxy->options2 & PR_O2_RDPC_PRST)
4351 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4352 }
4353
Willy Tarreaue6b98942007-10-29 01:09:36 +01004354 /* adjust this proxy's listeners */
4355 listener = curproxy->listen;
4356 while (listener) {
4357 if (curproxy->options & PR_O_TCP_NOLING)
4358 listener->options |= LI_O_NOLINGER;
4359 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004360 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004361 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004362 listener->accept = event_accept;
4363 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004364 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004365 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004366
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004367 /* smart accept mode is automatic in HTTP mode */
4368 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4369 (curproxy->mode == PR_MODE_HTTP &&
4370 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4371 listener->options |= LI_O_NOQUICKACK;
4372
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004373 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004374 listener = listener->next;
4375 }
4376
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 curproxy = curproxy->next;
4378 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004379
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004380 /*
4381 * Recount currently required checks.
4382 */
4383
4384 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4385 int optnum;
4386
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004387 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4388 if (curproxy->options & cfg_opts[optnum].val)
4389 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004390
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004391 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4392 if (curproxy->options2 & cfg_opts2[optnum].val)
4393 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004394 }
4395
Willy Tarreaubb925012009-07-23 13:36:36 +02004396 if (cfgerr > 0)
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 out:
4399 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400}
4401
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004402/*
4403 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4404 * parsing sessions.
4405 */
4406void cfg_register_keywords(struct cfg_kw_list *kwl)
4407{
4408 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4409}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004411/*
4412 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4413 */
4414void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4415{
4416 LIST_DEL(&kwl->list);
4417 LIST_INIT(&kwl->list);
4418}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419
4420/*
4421 * Local variables:
4422 * c-indent-level: 8
4423 * c-basic-offset: 8
4424 * End:
4425 */