blob: bd720c62465331d091735ae2e1d103405ee36095 [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 Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020046#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010052#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/task.h>
54
55
Willy Tarreauf3c69202006-07-09 16:42:34 +020056/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
57 * ssl-hello-chk option to ensure that the remote server speaks SSL.
58 *
59 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
60 */
61const char sslv3_client_hello_pkt[] = {
62 "\x16" /* ContentType : 0x16 = Hanshake */
63 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
64 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
65 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
66 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
67 "\x03\x00" /* Hello Version : 0x0300 = v3 */
68 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
69 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
70 "\x00" /* Session ID length : empty (no session ID) */
71 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
72 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
73 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
74 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
75 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
76 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
77 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
78 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
79 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
80 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
81 "\x00\x38" "\x00\x39" "\x00\x3A"
82 "\x01" /* Compression Length : 0x01 = 1 byte for types */
83 "\x00" /* Compression Type : 0x00 = NULL compression */
84};
85
Willy Tarreau3842f002009-06-14 11:39:52 +020086/* various keyword modifiers */
87enum kw_mod {
88 KWM_STD = 0, /* normal */
89 KWM_NO, /* "no" prefixed before the keyword */
90 KWM_DEF, /* "default" prefixed before the keyword */
91};
92
Willy Tarreau13943ab2006-12-31 00:24:10 +010093/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010094struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010095 const char *name;
96 unsigned int val;
97 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010098 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010099};
100
101/* proxy->options */
102static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100104 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100105 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100108 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
109 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
110 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
111 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
112 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
113 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
114 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
115 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100117 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
118 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100119#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100120 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
121#endif
122#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 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200141 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200142 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143 { NULL, 0, 0, 0 }
144};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200145
Willy Tarreau6daf3432008-01-22 16:44:08 +0100146static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200147static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
148int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100149int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200151/* List head of all known configuration keywords */
152static struct cfg_kw_list cfg_keywords = {
153 .list = LIST_HEAD_INIT(cfg_keywords.list)
154};
155
Willy Tarreaubaaee002006-06-26 02:48:02 +0200156/*
157 * converts <str> to a list of listeners which are dynamically allocated.
158 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
159 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
160 * - <port> is a numerical port from 1 to 65535 ;
161 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
162 * This can be repeated as many times as necessary, separated by a coma.
163 * The <tail> argument is a pointer to a current list which should be appended
164 * to the tail of the new list. The pointer to the new list is returned.
165 */
166static struct listener *str2listener(char *str, struct listener *tail)
167{
168 struct listener *l;
169 char *c, *next, *range, *dupstr;
170 int port, end;
171
172 next = dupstr = strdup(str);
173
174 while (next && *next) {
175 struct sockaddr_storage ss;
176
177 str = next;
178 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100179 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180 *next++ = 0;
181 }
182
183 /* 2) look for the addr/port delimiter, it's the last colon. */
184 if ((range = strrchr(str, ':')) == NULL) {
185 Alert("Missing port number: '%s'\n", str);
186 goto fail;
187 }
188
189 *range++ = 0;
190
191 if (strrchr(str, ':') != NULL) {
192 /* IPv6 address contains ':' */
193 memset(&ss, 0, sizeof(ss));
194 ss.ss_family = AF_INET6;
195
196 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
197 Alert("Invalid server address: '%s'\n", str);
198 goto fail;
199 }
200 }
201 else {
202 memset(&ss, 0, sizeof(ss));
203 ss.ss_family = AF_INET;
204
205 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
206 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
207 }
208 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
209 struct hostent *he;
210
211 if ((he = gethostbyname(str)) == NULL) {
212 Alert("Invalid server name: '%s'\n", str);
213 goto fail;
214 }
215 else
216 ((struct sockaddr_in *)&ss)->sin_addr =
217 *(struct in_addr *) *(he->h_addr_list);
218 }
219 }
220
221 /* 3) look for the port-end delimiter */
222 if ((c = strchr(range, '-')) != NULL) {
223 *c++ = 0;
224 end = atol(c);
225 }
226 else {
227 end = atol(range);
228 }
229
230 port = atol(range);
231
232 if (port < 1 || port > 65535) {
233 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
234 goto fail;
235 }
236
237 if (end < 1 || end > 65535) {
238 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
239 goto fail;
240 }
241
242 for (; port <= end; port++) {
243 l = (struct listener *)calloc(1, sizeof(struct listener));
244 l->next = tail;
245 tail = l;
246
247 l->fd = -1;
248 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100249 l->state = LI_INIT;
250
251 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100253 tcpv6_add_listener(l);
254 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100256 tcpv4_add_listener(l);
257 }
258 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 } /* end for(port) */
260 } /* end while(next) */
261 free(dupstr);
262 return tail;
263 fail:
264 free(dupstr);
265 return NULL;
266}
267
Willy Tarreau977b8e42006-12-29 14:19:17 +0100268/*
269 * Sends a warning if proxy <proxy> does not have at least one of the
270 * capabilities in <cap>. An optionnal <hint> may be added at the end
271 * of the warning to help the user. Returns 1 if a warning was emitted
272 * or 0 if the condition is valid.
273 */
274int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
275{
276 char *msg;
277
278 switch (cap) {
279 case PR_CAP_BE: msg = "no backend"; break;
280 case PR_CAP_FE: msg = "no frontend"; break;
281 case PR_CAP_RS: msg = "no ruleset"; break;
282 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
283 default: msg = "not enough"; break;
284 }
285
286 if (!(proxy->cap & cap)) {
287 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100288 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100289 return 1;
290 }
291 return 0;
292}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293
Willy Tarreau61d18892009-03-31 10:49:21 +0200294/* Report a warning if a rule is placed after a 'block' rule.
295 * Return 1 if the warning has been emitted, otherwise 0.
296 */
297int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
298{
299 if (!LIST_ISEMPTY(&proxy->block_cond)) {
300 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
301 file, line, arg);
302 return 1;
303 }
304 return 0;
305}
306
307/* Report a warning if a rule is placed after a reqrewrite rule.
308 * Return 1 if the warning has been emitted, otherwise 0.
309 */
310int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
311{
312 if (proxy->req_exp) {
313 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
314 file, line, arg);
315 return 1;
316 }
317 return 0;
318}
319
320/* Report a warning if a rule is placed after a reqadd rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
324{
325 if (proxy->nb_reqadd) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a redirect rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
336int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
337{
338 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a 'use_backend' rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
349int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
350{
351 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* report a warning if a block rule is dangerously placed */
360int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
361{
362 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
363 warnif_rule_after_reqadd(proxy, file, line, arg) ||
364 warnif_rule_after_redirect(proxy, file, line, arg) ||
365 warnif_rule_after_use_backend(proxy, file, line, arg);
366}
367
368/* report a warning if a reqxxx rule is dangerously placed */
369int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
370{
371 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
372 warnif_rule_after_redirect(proxy, file, line, arg) ||
373 warnif_rule_after_use_backend(proxy, file, line, arg);
374}
375
376/* report a warning if a reqadd rule is dangerously placed */
377int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
378{
379 return warnif_rule_after_redirect(proxy, file, line, arg) ||
380 warnif_rule_after_use_backend(proxy, file, line, arg);
381}
382
Willy Tarreaubaaee002006-06-26 02:48:02 +0200383/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200384 * parse a line in a <global> section. Returns the error code, 0 if OK, or
385 * any combination of :
386 * - ERR_ABORT: must abort ASAP
387 * - ERR_FATAL: we can continue parsing but not start the service
388 * - ERR_WARN: a warning has been emitted
389 * - ERR_ALERT: an alert has been emitted
390 * Only the two first ones can stop processing, the two others are just
391 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200392 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200393int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200394{
Willy Tarreau058e9072009-07-20 09:30:05 +0200395 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200396
397 if (!strcmp(args[0], "global")) { /* new section */
398 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400 }
401 else if (!strcmp(args[0], "daemon")) {
402 global.mode |= MODE_DAEMON;
403 }
404 else if (!strcmp(args[0], "debug")) {
405 global.mode |= MODE_DEBUG;
406 }
407 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100408 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200409 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200410 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100411 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200412 }
413 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100414 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200416 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100417 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200418 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100419 else if (!strcmp(args[0], "nosplice")) {
420 global.tune.options &= ~GTUNE_USE_SPLICE;
421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200422 else if (!strcmp(args[0], "quiet")) {
423 global.mode |= MODE_QUIET;
424 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200425 else if (!strcmp(args[0], "tune.maxpollevents")) {
426 if (global.tune.maxpollevents != 0) {
427 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200428 err_code |= ERR_ALERT;
429 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200433 err_code |= ERR_ALERT | ERR_FATAL;
434 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200435 }
436 global.tune.maxpollevents = atol(args[1]);
437 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100438 else if (!strcmp(args[0], "tune.maxaccept")) {
439 if (global.tune.maxaccept != 0) {
440 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200441 err_code |= ERR_ALERT;
442 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100443 }
444 if (*(args[1]) == 0) {
445 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 err_code |= ERR_ALERT | ERR_FATAL;
447 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100448 }
449 global.tune.maxaccept = atol(args[1]);
450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 else if (!strcmp(args[0], "uid")) {
452 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200453 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 err_code |= ERR_ALERT;
455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456 }
457 if (*(args[1]) == 0) {
458 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 err_code |= ERR_ALERT | ERR_FATAL;
460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
462 global.uid = atol(args[1]);
463 }
464 else if (!strcmp(args[0], "gid")) {
465 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200466 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200467 err_code |= ERR_ALERT;
468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
470 if (*(args[1]) == 0) {
471 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200472 err_code |= ERR_ALERT | ERR_FATAL;
473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 }
475 global.gid = atol(args[1]);
476 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200477 /* user/group name handling */
478 else if (!strcmp(args[0], "user")) {
479 struct passwd *ha_user;
480 if (global.uid != 0) {
481 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 err_code |= ERR_ALERT;
483 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200484 }
485 errno = 0;
486 ha_user = getpwnam(args[1]);
487 if (ha_user != NULL) {
488 global.uid = (int)ha_user->pw_uid;
489 }
490 else {
491 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 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200493 }
494 }
495 else if (!strcmp(args[0], "group")) {
496 struct group *ha_group;
497 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200498 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT;
500 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200501 }
502 errno = 0;
503 ha_group = getgrnam(args[1]);
504 if (ha_group != NULL) {
505 global.gid = (int)ha_group->gr_gid;
506 }
507 else {
508 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 +0200509 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200510 }
511 }
512 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200513 else if (!strcmp(args[0], "nbproc")) {
514 if (global.nbproc != 0) {
515 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT;
517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
524 global.nbproc = atol(args[1]);
525 }
526 else if (!strcmp(args[0], "maxconn")) {
527 if (global.maxconn != 0) {
528 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200529 err_code |= ERR_ALERT;
530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531 }
532 if (*(args[1]) == 0) {
533 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 }
537 global.maxconn = atol(args[1]);
538#ifdef SYSTEM_MAXCONN
539 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
540 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);
541 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200543 }
544#endif /* SYSTEM_MAXCONN */
545 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100546 else if (!strcmp(args[0], "maxpipes")) {
547 if (global.maxpipes != 0) {
548 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200549 err_code |= ERR_ALERT;
550 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100551 }
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100556 }
557 global.maxpipes = atol(args[1]);
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "ulimit-n")) {
560 if (global.rlimit_nofile != 0) {
561 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200562 err_code |= ERR_ALERT;
563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 }
565 if (*(args[1]) == 0) {
566 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 }
570 global.rlimit_nofile = atol(args[1]);
571 }
572 else if (!strcmp(args[0], "chroot")) {
573 if (global.chroot != NULL) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200575 err_code |= ERR_ALERT;
576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 }
583 global.chroot = strdup(args[1]);
584 }
585 else if (!strcmp(args[0], "pidfile")) {
586 if (global.pidfile != NULL) {
587 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 err_code |= ERR_ALERT;
589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 }
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 global.pidfile = strdup(args[1]);
597 }
598 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100599 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200600 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601
602 if (*(args[1]) == 0 || *(args[2]) == 0) {
603 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 }
607
608 facility = get_log_facility(args[2]);
609 if (facility < 0) {
610 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614
615 level = 7; /* max syslog level = debug */
616 if (*(args[3])) {
617 level = get_log_level(args[3]);
618 if (level < 0) {
619 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
621 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 }
624
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200625 minlvl = 0; /* limit syslog level to this level (emerg) */
626 if (*(args[4])) {
627 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200629 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT | ERR_FATAL;
631 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200632 }
633 }
634
Robert Tsai81ae1952007-12-05 10:47:29 +0100635 if (args[1][0] == '/') {
636 logsrv.u.addr.sa_family = AF_UNIX;
637 logsrv.u.un = *str2sun(args[1]);
638 } else {
639 logsrv.u.addr.sa_family = AF_INET;
640 logsrv.u.in = *str2sa(args[1]);
641 if (!logsrv.u.in.sin_port)
642 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644
645 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100646 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 global.logfac1 = facility;
648 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200649 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 }
651 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100652 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 global.logfac2 = facility;
654 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200655 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
657 else {
658 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200661 }
662 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
663 if (global.spread_checks != 0) {
664 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT;
666 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200672 }
673 global.spread_checks = atol(args[1]);
674 if (global.spread_checks < 0 || global.spread_checks > 50) {
675 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 }
679 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200680 struct cfg_kw_list *kwl;
681 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200682 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200683
684 list_for_each_entry(kwl, &cfg_keywords.list, list) {
685 for (index = 0; kwl->kw[index].kw != NULL; index++) {
686 if (kwl->kw[index].section != CFG_GLOBAL)
687 continue;
688 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
689 /* prepare error message just in case */
690 snprintf(trash, sizeof(trash),
691 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200692 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
693 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200694 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200696 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200697 else if (rc > 0) {
698 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_WARN;
700 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200701 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200702 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200703 }
704 }
705 }
706
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200710 out:
711 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200712}
713
714
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200715void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716{
717 memset(&defproxy, 0, sizeof(defproxy));
718 defproxy.mode = PR_MODE_TCP;
719 defproxy.state = PR_STNEW;
720 defproxy.maxconn = cfg_maxpconn;
721 defproxy.conn_retries = CONN_RETRIES;
722 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200723
724 LIST_INIT(&defproxy.pendconns);
725 LIST_INIT(&defproxy.acl);
726 LIST_INIT(&defproxy.block_cond);
727 LIST_INIT(&defproxy.mon_fail_cond);
728 LIST_INIT(&defproxy.switching_rules);
729
Willy Tarreau3a70f942008-02-15 11:15:34 +0100730 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731}
732
733/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100734 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200735 * Returns the error code, 0 if OK, or any combination of :
736 * - ERR_ABORT: must abort ASAP
737 * - ERR_FATAL: we can continue parsing but not start the service
738 * - ERR_WARN: a warning has been emitted
739 * - ERR_ALERT: an alert has been emitted
740 * Only the two first ones can stop processing, the two others are just
741 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200743int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744{
745 static struct proxy *curproxy = NULL;
746 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200747 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100748 int rc;
749 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200750 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751
Willy Tarreau977b8e42006-12-29 14:19:17 +0100752 if (!strcmp(args[0], "listen"))
753 rc = PR_CAP_LISTEN;
754 else if (!strcmp(args[0], "frontend"))
755 rc = PR_CAP_FE | PR_CAP_RS;
756 else if (!strcmp(args[0], "backend"))
757 rc = PR_CAP_BE | PR_CAP_RS;
758 else if (!strcmp(args[0], "ruleset"))
759 rc = PR_CAP_RS;
760 else
761 rc = PR_CAP_NONE;
762
763 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 if (!*args[1]) {
765 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
766 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200768 err_code |= ERR_ALERT | ERR_ABORT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200771
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100772 err = invalid_char(args[1]);
773 if (err) {
774 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
775 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200776 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100777 }
778
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200779 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
780 /*
781 * If there are two proxies with the same name only following
782 * combinations are allowed:
783 *
784 * listen backend frontend ruleset
785 * listen - - - -
786 * backend - - OK -
787 * frontend - OK - -
788 * ruleset - - - -
789 */
790
791 if (!strcmp(curproxy->id, args[1]) &&
792 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
793 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100794 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
795 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Willy Tarreau93893792009-07-23 13:19:11 +0200796 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200797 }
798 }
799
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
801 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200802 err_code |= ERR_ALERT | ERR_ABORT;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100805
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 curproxy->next = proxy;
807 proxy = curproxy;
808 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200809 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200810 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200811 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100812 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200813 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200814 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815
Willy Tarreauee991362007-05-14 14:37:50 +0200816 /* Timeouts are defined as -1, so we cannot use the zeroed area
817 * as a default value.
818 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100819 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200820
821 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824
825 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100826 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 curproxy->listen = str2listener(args[2], curproxy->listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200828 if (!curproxy->listen) {
829 err_code |= ERR_FATAL;
830 goto out;
831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 global.maxsock++;
833 }
834
835 /* set default values */
836 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100838 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200839 curproxy->no_options = defproxy.no_options;
840 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100841 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100842 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200843 curproxy->except_net = defproxy.except_net;
844 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200845 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200846 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200848 if (defproxy.fwdfor_hdr_len) {
849 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
850 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
851 }
852
Willy Tarreau977b8e42006-12-29 14:19:17 +0100853 if (curproxy->cap & PR_CAP_FE) {
854 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100855 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200856 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100857
858 /* initialize error relocations */
859 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
860 if (defproxy.errmsg[rc].str)
861 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
862 }
863
864 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866
Willy Tarreau977b8e42006-12-29 14:19:17 +0100867 if (curproxy->cap & PR_CAP_BE) {
868 curproxy->fullconn = defproxy.fullconn;
869 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870
Willy Tarreau977b8e42006-12-29 14:19:17 +0100871 if (defproxy.check_req)
872 curproxy->check_req = strdup(defproxy.check_req);
873 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874
Willy Tarreau977b8e42006-12-29 14:19:17 +0100875 if (defproxy.cookie_name)
876 curproxy->cookie_name = strdup(defproxy.cookie_name);
877 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100878
Emeric Brun647caf12009-06-30 17:57:00 +0200879 if (defproxy.rdp_cookie_name)
880 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
881 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
882
Willy Tarreau01732802007-11-01 22:48:15 +0100883 if (defproxy.url_param_name)
884 curproxy->url_param_name = strdup(defproxy.url_param_name);
885 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100886
Benoitaffb4812009-03-25 13:02:10 +0100887 if (defproxy.hh_name)
888 curproxy->hh_name = strdup(defproxy.hh_name);
889 curproxy->hh_len = defproxy.hh_len;
890 curproxy->hh_match_domain = defproxy.hh_match_domain;
891
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100892 if (defproxy.iface_name)
893 curproxy->iface_name = strdup(defproxy.iface_name);
894 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200897 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100898 if (defproxy.capture_name)
899 curproxy->capture_name = strdup(defproxy.capture_name);
900 curproxy->capture_namelen = defproxy.capture_namelen;
901 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903
Willy Tarreau977b8e42006-12-29 14:19:17 +0100904 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100905 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100906 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100907 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100908 curproxy->uri_auth = defproxy.uri_auth;
909 curproxy->mon_net = defproxy.mon_net;
910 curproxy->mon_mask = defproxy.mon_mask;
911 if (defproxy.monitor_uri)
912 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
913 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100914 if (defproxy.defbe.name)
915 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100916 }
917
918 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100919 curproxy->timeout.connect = defproxy.timeout.connect;
920 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100921 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100922 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100923 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +0200924 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100925 curproxy->source_addr = defproxy.source_addr;
926 }
927
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 curproxy->mode = defproxy.mode;
929 curproxy->logfac1 = defproxy.logfac1;
930 curproxy->logsrv1 = defproxy.logsrv1;
931 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 curproxy->logfac2 = defproxy.logfac2;
934 curproxy->logsrv2 = defproxy.logsrv2;
935 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200936 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100938 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
939 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200940
Willy Tarreau93893792009-07-23 13:19:11 +0200941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
944 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100945 /* FIXME-20070101: we should do this too at the end of the
946 * config parsing to free all default values.
947 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200948 free(defproxy.check_req);
949 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +0200950 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200951 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100952 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200953 free(defproxy.capture_name);
954 free(defproxy.monitor_uri);
955 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100956 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200957 free(defproxy.fwdfor_hdr_name);
958 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100959
Willy Tarreaua534fea2008-08-03 12:19:50 +0200960 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
961 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100962
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 /* we cannot free uri_auth because it might already be used */
964 init_default_instance();
965 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100966 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +0200967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 else if (curproxy == NULL) {
970 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974
Willy Tarreau977b8e42006-12-29 14:19:17 +0100975
976 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100978 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100979 int cur_arg;
980
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 if (curproxy == &defproxy) {
982 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100986 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +0200987 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988
989 if (strchr(args[1], ':') == NULL) {
990 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100995
996 last_listen = curproxy->listen;
997 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200998 if (!curproxy->listen) {
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001002
1003 cur_arg = 2;
1004 while (*(args[cur_arg])) {
1005 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1006#ifdef SO_BINDTODEVICE
1007 struct listener *l;
1008
1009 if (!*args[cur_arg + 1]) {
1010 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1011 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001014 }
1015
1016 for (l = curproxy->listen; l != last_listen; l = l->next)
1017 l->interface = strdup(args[cur_arg + 1]);
1018
1019 global.last_checks |= LSTCHK_NETADM;
1020
1021 cur_arg += 2;
1022 continue;
1023#else
1024 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1025 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001028#endif
1029 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001030 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1031#ifdef TCP_MAXSEG
1032 struct listener *l;
1033 int mss;
1034
1035 if (!*args[cur_arg + 1]) {
1036 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001040 }
1041
1042 mss = str2uic(args[cur_arg + 1]);
1043 if (mss < 1 || mss > 65535) {
1044 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1045 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001048 }
1049
1050 for (l = curproxy->listen; l != last_listen; l = l->next)
1051 l->maxseg = mss;
1052
1053 cur_arg += 2;
1054 continue;
1055#else
1056 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1057 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001060#endif
1061 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001062 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001063#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001064 struct listener *l;
1065
1066 for (l = curproxy->listen; l != last_listen; l = l->next)
1067 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001068
1069 cur_arg ++;
1070 continue;
1071#else
1072 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1073 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001076#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001077 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001078 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 }
1086 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1087 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1088 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1089 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001093 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001094 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001095
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 /* flush useless bits */
1097 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001100 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001101 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001102 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001103
Willy Tarreau1c47f852006-07-09 08:22:27 +02001104 if (!*args[1]) {
1105 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001109 }
1110
Willy Tarreaua534fea2008-08-03 12:19:50 +02001111 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001112 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001113 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001114 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001115 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1116
Willy Tarreau93893792009-07-23 13:19:11 +02001117 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1120 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1121 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1122 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1123 else {
1124 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001129 else if (!strcmp(args[0], "id")) {
1130 struct proxy *target;
1131
1132 if (curproxy == &defproxy) {
1133 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001137 }
1138
1139 if (!*args[1]) {
1140 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001144 }
1145
1146 curproxy->uuid = atol(args[1]);
1147
1148 if (curproxy->uuid < 1001) {
1149 Alert("parsing [%s:%d]: custom id has to be > 1000",
1150 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001153 }
1154
1155 for (target = proxy; target; target = target->next)
1156 if (curproxy != target && curproxy->uuid == target->uuid) {
1157 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1158 file, linenum, curproxy->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001161 }
1162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1164 curproxy->state = PR_STSTOPPED;
1165 }
1166 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1167 curproxy->state = PR_STNEW;
1168 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001169 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1170 int cur_arg = 1;
1171 unsigned int set = 0;
1172
1173 while (*args[cur_arg]) {
1174 int u;
1175 if (strcmp(args[cur_arg], "all") == 0) {
1176 set = 0;
1177 break;
1178 }
1179 else if (strcmp(args[cur_arg], "odd") == 0) {
1180 set |= 0x55555555;
1181 }
1182 else if (strcmp(args[cur_arg], "even") == 0) {
1183 set |= 0xAAAAAAAA;
1184 }
1185 else {
1186 u = str2uic(args[cur_arg]);
1187 if (u < 1 || u > 32) {
1188 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1189 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001192 }
1193 if (u > global.nbproc) {
1194 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1195 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001196 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001197 }
1198 set |= 1 << (u - 1);
1199 }
1200 cur_arg++;
1201 }
1202 curproxy->bind_proc = set;
1203 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001204 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001205 if (curproxy == &defproxy) {
1206 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001209 }
1210
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001211 err = invalid_char(args[1]);
1212 if (err) {
1213 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1214 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001216 }
1217
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001218 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1219 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1220 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001223 }
1224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1226 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227
Willy Tarreau977b8e42006-12-29 14:19:17 +01001228 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001229 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001230
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1233 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001237
1238 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001239 curproxy->cookie_name = strdup(args[1]);
1240 curproxy->cookie_len = strlen(curproxy->cookie_name);
1241
1242 cur_arg = 2;
1243 while (*(args[cur_arg])) {
1244 if (!strcmp(args[cur_arg], "rewrite")) {
1245 curproxy->options |= PR_O_COOK_RW;
1246 }
1247 else if (!strcmp(args[cur_arg], "indirect")) {
1248 curproxy->options |= PR_O_COOK_IND;
1249 }
1250 else if (!strcmp(args[cur_arg], "insert")) {
1251 curproxy->options |= PR_O_COOK_INS;
1252 }
1253 else if (!strcmp(args[cur_arg], "nocache")) {
1254 curproxy->options |= PR_O_COOK_NOC;
1255 }
1256 else if (!strcmp(args[cur_arg], "postonly")) {
1257 curproxy->options |= PR_O_COOK_POST;
1258 }
1259 else if (!strcmp(args[cur_arg], "prefix")) {
1260 curproxy->options |= PR_O_COOK_PFX;
1261 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001262 else if (!strcmp(args[cur_arg], "domain")) {
1263 if (!*args[cur_arg + 1]) {
1264 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1265 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001268 }
1269
1270 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1271 /* rfc2109, 4.3.2 Rejecting Cookies */
1272 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1273 " dots or does not start with a dot.\n",
1274 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001277 }
1278
1279 err = invalid_domainchar(args[cur_arg + 1]);
1280 if (err) {
1281 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1282 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001285 }
1286
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001287 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001288 cur_arg++;
1289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001290 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001291 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001295 }
1296 cur_arg++;
1297 }
1298 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1299 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001301 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 }
1303
1304 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1305 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1306 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001307 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
1309 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001310 else if (!strcmp(args[0], "persist")) { /* persist */
1311 if (*(args[1]) == 0) {
1312 Alert("parsing [%s:%d] : missing persist method.\n",
1313 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001314 err_code |= ERR_ALERT | ERR_FATAL;
1315 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001316 }
1317
1318 if (!strncmp(args[1], "rdp-cookie", 10)) {
1319 curproxy->options2 |= PR_O2_RDPC_PRST;
1320
1321 if (*(args[1] + 10 ) == '(') { /* cookie name */
1322 const char *beg, *end;
1323
1324 beg = args[1] + 11;
1325 end = strchr(beg, ')');
1326
1327 if (!end || end == beg) {
1328 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1329 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001332 }
1333
1334 free(curproxy->rdp_cookie_name);
1335 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1336 curproxy->rdp_cookie_len = end-beg;
1337 }
1338 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1339 free(curproxy->rdp_cookie_name);
1340 curproxy->rdp_cookie_name = strdup("msts");
1341 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1342 }
1343 else { /* syntax */
1344 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1345 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001348 }
1349 }
1350 else {
1351 Alert("parsing [%s:%d] : unknown persist method.\n",
1352 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001355 }
1356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358
Willy Tarreau977b8e42006-12-29 14:19:17 +01001359 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001361
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 if (*(args[5]) == 0) {
1363 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
1368 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001369 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 curproxy->appsession_name = strdup(args[1]);
1371 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1372 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001373 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1374 if (err) {
1375 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1376 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001379 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001380 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001381
Willy Tarreau51041c72007-09-09 21:56:53 +02001382 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1383 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001384 err_code |= ERR_ALERT | ERR_ABORT;
1385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 }
1387 } /* Url App Session */
1388 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001389 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001391
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 if (*(args[4]) == 0) {
1394 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001399 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 curproxy->capture_name = strdup(args[2]);
1401 curproxy->capture_namelen = strlen(curproxy->capture_name);
1402 curproxy->capture_len = atol(args[4]);
1403 if (curproxy->capture_len >= CAPTURE_LEN) {
1404 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1405 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 curproxy->capture_len = CAPTURE_LEN - 1;
1408 }
1409 curproxy->to_log |= LW_COOKIE;
1410 }
1411 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1412 struct cap_hdr *hdr;
1413
1414 if (curproxy == &defproxy) {
1415 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 +02001416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 }
1419
1420 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1421 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1422 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001423 err_code |= ERR_ALERT | ERR_FATAL;
1424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 }
1426
1427 hdr = calloc(sizeof(struct cap_hdr), 1);
1428 hdr->next = curproxy->req_cap;
1429 hdr->name = strdup(args[3]);
1430 hdr->namelen = strlen(args[3]);
1431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 hdr->index = curproxy->nb_req_cap++;
1434 curproxy->req_cap = hdr;
1435 curproxy->to_log |= LW_REQHDR;
1436 }
1437 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1438 struct cap_hdr *hdr;
1439
1440 if (curproxy == &defproxy) {
1441 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 +02001442 err_code |= ERR_ALERT | ERR_FATAL;
1443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 }
1445
1446 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1447 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1448 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001449 err_code |= ERR_ALERT | ERR_FATAL;
1450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 }
1452 hdr = calloc(sizeof(struct cap_hdr), 1);
1453 hdr->next = curproxy->rsp_cap;
1454 hdr->name = strdup(args[3]);
1455 hdr->namelen = strlen(args[3]);
1456 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001457 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 hdr->index = curproxy->nb_rsp_cap++;
1459 curproxy->rsp_cap = hdr;
1460 curproxy->to_log |= LW_RSPHDR;
1461 }
1462 else {
1463 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
1466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 }
1468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 if (*(args[1]) == 0) {
1474 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001476 err_code |= ERR_ALERT | ERR_FATAL;
1477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 }
1479 curproxy->conn_retries = atol(args[1]);
1480 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001481 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1482 int pol = ACL_COND_NONE;
1483 struct acl_cond *cond;
1484
Willy Tarreaub099aca2008-10-12 17:26:37 +02001485 if (curproxy == &defproxy) {
1486 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001487 err_code |= ERR_ALERT | ERR_FATAL;
1488 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001489 }
1490
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001491 if (!strcmp(args[1], "if"))
1492 pol = ACL_COND_IF;
1493 else if (!strcmp(args[1], "unless"))
1494 pol = ACL_COND_UNLESS;
1495
1496 if (pol == ACL_COND_NONE) {
1497 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001501 }
1502
1503 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1504 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001508 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001509 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001510 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001511 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001512 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001513 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001514 else if (!strcmp(args[0], "redirect")) {
1515 int pol = ACL_COND_NONE;
1516 struct acl_cond *cond;
1517 struct redirect_rule *rule;
1518 int cur_arg;
1519 int type = REDIRECT_TYPE_NONE;
1520 int code = 302;
1521 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001522 char *cookie = NULL;
1523 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001524 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001525
1526 cur_arg = 1;
1527 while (*(args[cur_arg])) {
1528 if (!strcmp(args[cur_arg], "location")) {
1529 if (!*args[cur_arg + 1]) {
1530 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1531 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001534 }
1535
1536 type = REDIRECT_TYPE_LOCATION;
1537 cur_arg++;
1538 destination = args[cur_arg];
1539 }
1540 else if (!strcmp(args[cur_arg], "prefix")) {
1541 if (!*args[cur_arg + 1]) {
1542 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1543 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001546 }
1547
1548 type = REDIRECT_TYPE_PREFIX;
1549 cur_arg++;
1550 destination = args[cur_arg];
1551 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001552 else if (!strcmp(args[cur_arg], "set-cookie")) {
1553 if (!*args[cur_arg + 1]) {
1554 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1555 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001558 }
1559
1560 cur_arg++;
1561 cookie = args[cur_arg];
1562 cookie_set = 1;
1563 }
1564 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1565 if (!*args[cur_arg + 1]) {
1566 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1567 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001568 err_code |= ERR_ALERT | ERR_FATAL;
1569 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001570 }
1571
1572 cur_arg++;
1573 cookie = args[cur_arg];
1574 cookie_set = 0;
1575 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001576 else if (!strcmp(args[cur_arg],"code")) {
1577 if (!*args[cur_arg + 1]) {
1578 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001582 }
1583 cur_arg++;
1584 code = atol(args[cur_arg]);
1585 if (code < 301 || code > 303) {
1586 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1587 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001588 err_code |= ERR_ALERT | ERR_FATAL;
1589 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001590 }
1591 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001592 else if (!strcmp(args[cur_arg],"drop-query")) {
1593 flags |= REDIRECT_FLAG_DROP_QS;
1594 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001595 else if (!strcmp(args[cur_arg], "if")) {
1596 pol = ACL_COND_IF;
1597 cur_arg++;
1598 break;
1599 }
1600 else if (!strcmp(args[cur_arg], "unless")) {
1601 pol = ACL_COND_UNLESS;
1602 cur_arg++;
1603 break;
1604 }
1605 else {
1606 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1607 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001608 err_code |= ERR_ALERT | ERR_FATAL;
1609 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001610 }
1611 cur_arg++;
1612 }
1613
1614 if (type == REDIRECT_TYPE_NONE) {
1615 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001619 }
1620
1621 if (pol == ACL_COND_NONE) {
1622 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001626 }
1627
1628 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001629 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001630 file, linenum, args[0]);
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
Willy Tarreaua9802632008-07-25 19:13:19 +02001635 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001636 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001637 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1638 rule->cond = cond;
1639 rule->rdr_str = strdup(destination);
1640 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001641 if (cookie) {
1642 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1643 * a clear consists in appending "; Max-Age=0" at the end.
1644 */
1645 rule->cookie_len = strlen(cookie);
1646 if (cookie_set)
1647 rule->cookie_str = strdup(cookie);
1648 else {
1649 rule->cookie_str = malloc(rule->cookie_len + 12);
1650 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1651 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1652 rule->cookie_len += 11;
1653 }
1654 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001655 rule->type = type;
1656 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001657 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001658 LIST_INIT(&rule->list);
1659 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001660 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001661 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001662 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001663 int pol = ACL_COND_NONE;
1664 struct acl_cond *cond;
1665 struct switching_rule *rule;
1666
Willy Tarreaub099aca2008-10-12 17:26:37 +02001667 if (curproxy == &defproxy) {
1668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001671 }
1672
Willy Tarreau55ea7572007-06-17 19:56:27 +02001673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001675
1676 if (*(args[1]) == 0) {
1677 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001680 }
1681
1682 if (!strcmp(args[2], "if"))
1683 pol = ACL_COND_IF;
1684 else if (!strcmp(args[2], "unless"))
1685 pol = ACL_COND_UNLESS;
1686
1687 if (pol == ACL_COND_NONE) {
1688 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001692 }
1693
1694 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001695 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001699 }
1700
Willy Tarreaua9802632008-07-25 19:13:19 +02001701 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001702 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001703 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001704 struct acl *acl;
1705 const char *name;
1706
1707 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1708 name = acl ? acl->name : "(unknown)";
1709 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1710 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001712 }
1713
Willy Tarreau55ea7572007-06-17 19:56:27 +02001714 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1715 rule->cond = cond;
1716 rule->be.name = strdup(args[1]);
1717 LIST_INIT(&rule->list);
1718 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001723
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1725 curproxy->uri_auth = NULL; /* we must detach from the default config */
1726
1727 if (*(args[1]) == 0) {
1728 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 } else if (!strcmp(args[1], "uri")) {
1732 if (*(args[2]) == 0) {
1733 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
1735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1737 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_ABORT;
1739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 }
1741 } else if (!strcmp(args[1], "realm")) {
1742 if (*(args[2]) == 0) {
1743 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1747 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_ALERT | ERR_ABORT;
1749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001751 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001752 unsigned interval;
1753
1754 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1755 if (err) {
1756 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1757 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001760 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1761 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001762 err_code |= ERR_ALERT | ERR_ABORT;
1763 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 } else if (!strcmp(args[1], "auth")) {
1766 if (*(args[2]) == 0) {
1767 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1771 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_ABORT;
1773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 }
1775 } else if (!strcmp(args[1], "scope")) {
1776 if (*(args[2]) == 0) {
1777 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1781 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_ABORT;
1783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 }
1785 } else if (!strcmp(args[1], "enable")) {
1786 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_ABORT;
1789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001791 } else if (!strcmp(args[1], "hide-version")) {
1792 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1793 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001794 err_code |= ERR_ALERT | ERR_ABORT;
1795 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001798 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803 }
1804 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001805 int optnum;
1806
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001807 if (*(args[1]) == '\0') {
1808 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001813
1814 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1815 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001816 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1817 err_code |= ERR_WARN;
1818 goto out;
1819 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001820
Willy Tarreau3842f002009-06-14 11:39:52 +02001821 curproxy->no_options &= ~cfg_opts[optnum].val;
1822 curproxy->options &= ~cfg_opts[optnum].val;
1823
1824 switch (kwm) {
1825 case KWM_STD:
1826 curproxy->options |= cfg_opts[optnum].val;
1827 break;
1828 case KWM_NO:
1829 curproxy->no_options |= cfg_opts[optnum].val;
1830 break;
1831 case KWM_DEF: /* already cleared */
1832 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001833 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001834
Willy Tarreau93893792009-07-23 13:19:11 +02001835 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001836 }
1837 }
1838
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001839 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1840 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001841 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1842 err_code |= ERR_WARN;
1843 goto out;
1844 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001845
Willy Tarreau3842f002009-06-14 11:39:52 +02001846 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1847 curproxy->options2 &= ~cfg_opts2[optnum].val;
1848
1849 switch (kwm) {
1850 case KWM_STD:
1851 curproxy->options2 |= cfg_opts2[optnum].val;
1852 break;
1853 case KWM_NO:
1854 curproxy->no_options2 |= cfg_opts2[optnum].val;
1855 break;
1856 case KWM_DEF: /* already cleared */
1857 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001858 }
Willy Tarreau93893792009-07-23 13:19:11 +02001859 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001860 }
1861 }
1862
Willy Tarreau3842f002009-06-14 11:39:52 +02001863 if (kwm != KWM_STD) {
1864 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001865 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001868 }
1869
Emeric Brun3a058f32009-06-30 18:26:00 +02001870 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02001872 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02001874 if (*(args[2]) != '\0') {
1875 if (!strcmp(args[2], "clf")) {
1876 curproxy->options2 |= PR_O2_CLFLOG;
1877 } else {
1878 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02001881 }
1882 }
1883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001884 else if (!strcmp(args[1], "tcplog"))
1885 /* generate a detailed TCP log */
1886 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 else if (!strcmp(args[1], "tcpka")) {
1888 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001889 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001891
1892 if (curproxy->cap & PR_CAP_FE)
1893 curproxy->options |= PR_O_TCP_CLI_KA;
1894 if (curproxy->cap & PR_CAP_BE)
1895 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 }
1897 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_WARN;
1900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001902 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001903 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001904 curproxy->options &= ~PR_O_SMTP_CHK;
1905 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 if (!*args[2]) { /* no argument */
1907 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1908 curproxy->check_len = strlen(DEF_CHECK_REQ);
1909 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001910 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 curproxy->check_req = (char *)malloc(reqlen);
1912 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1913 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1914 } else { /* more arguments : METHOD URI [HTTP_VER] */
1915 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1916 if (*args[4])
1917 reqlen += strlen(args[4]);
1918 else
1919 reqlen += strlen("HTTP/1.0");
1920
1921 curproxy->check_req = (char *)malloc(reqlen);
1922 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1923 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1924 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001925 }
1926 else if (!strcmp(args[1], "ssl-hello-chk")) {
1927 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001928 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001930
Willy Tarreaua534fea2008-08-03 12:19:50 +02001931 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001932 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001933 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001934 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
Willy Tarreau23677902007-05-08 23:50:35 +02001936 else if (!strcmp(args[1], "smtpchk")) {
1937 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001938 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001939 curproxy->options &= ~PR_O_HTTP_CHK;
1940 curproxy->options &= ~PR_O_SSL3_CHK;
1941 curproxy->options |= PR_O_SMTP_CHK;
1942
1943 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1944 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1945 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1946 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1947 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1948 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1949 curproxy->check_req = (char *)malloc(reqlen);
1950 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1951 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1952 } else {
1953 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1954 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1955 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1956 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1957 }
1958 }
1959 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001960 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001961 int cur_arg;
1962
1963 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1964 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001965 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001966
1967 curproxy->options |= PR_O_FWDFOR;
1968
1969 free(curproxy->fwdfor_hdr_name);
1970 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1971 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1972
1973 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1974 cur_arg = 2;
1975 while (*(args[cur_arg])) {
1976 if (!strcmp(args[cur_arg], "except")) {
1977 /* suboption except - needs additional argument for it */
1978 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1979 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1980 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001983 }
1984 /* flush useless bits */
1985 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001986 cur_arg += 2;
1987 } else if (!strcmp(args[cur_arg], "header")) {
1988 /* suboption header - needs additional argument for it */
1989 if (*(args[cur_arg+1]) == 0) {
1990 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1991 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02001994 }
1995 free(curproxy->fwdfor_hdr_name);
1996 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1997 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1998 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001999 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002000 /* unknown suboption - catchall */
2001 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2002 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002005 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002006 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002007 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002008 else if (!strcmp(args[1], "originalto")) {
2009 int cur_arg;
2010
2011 /* insert x-original-to field, but not for the IP address listed as an except.
2012 * set default options (ie: bitfield, header name, etc)
2013 */
2014
2015 curproxy->options |= PR_O_ORGTO;
2016
2017 free(curproxy->orgto_hdr_name);
2018 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2019 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2020
2021 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2022 cur_arg = 2;
2023 while (*(args[cur_arg])) {
2024 if (!strcmp(args[cur_arg], "except")) {
2025 /* suboption except - needs additional argument for it */
2026 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2027 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2028 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002031 }
2032 /* flush useless bits */
2033 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2034 cur_arg += 2;
2035 } else if (!strcmp(args[cur_arg], "header")) {
2036 /* suboption header - needs additional argument for it */
2037 if (*(args[cur_arg+1]) == 0) {
2038 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2039 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_ALERT | ERR_FATAL;
2041 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002042 }
2043 free(curproxy->orgto_hdr_name);
2044 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2045 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2046 cur_arg += 2;
2047 } else {
2048 /* unknown suboption - catchall */
2049 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2050 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002053 }
2054 } /* end while loop */
2055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 else {
2057 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 }
Willy Tarreau93893792009-07-23 13:19:11 +02002061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002063 else if (!strcmp(args[0], "default_backend")) {
2064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002066
2067 if (*(args[1]) == 0) {
2068 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_ALERT | ERR_FATAL;
2070 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002071 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002072 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002073 curproxy->defbe.name = strdup(args[1]);
2074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002077 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002079 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2080 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 /* enable reconnections to dispatch */
2083 curproxy->options |= PR_O_REDISP;
2084 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002085 else if (!strcmp(args[0], "http-check")) {
2086 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002088
2089 if (strcmp(args[1], "disable-on-404") == 0) {
2090 /* enable a graceful server shutdown on an HTTP 404 response */
2091 curproxy->options |= PR_O_DISABLE404;
2092 }
2093 else {
2094 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002097 }
2098 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002099 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002100 if (curproxy == &defproxy) {
2101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002104 }
2105
Willy Tarreaub80c2302007-11-30 20:51:32 +01002106 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002107 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002108
2109 if (strcmp(args[1], "fail") == 0) {
2110 /* add a condition to fail monitor requests */
2111 int pol = ACL_COND_NONE;
2112 struct acl_cond *cond;
2113
2114 if (!strcmp(args[2], "if"))
2115 pol = ACL_COND_IF;
2116 else if (!strcmp(args[2], "unless"))
2117 pol = ACL_COND_UNLESS;
2118
2119 if (pol == ACL_COND_NONE) {
2120 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2121 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_FATAL;
2123 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002124 }
2125
2126 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2127 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2128 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002131 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002132 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002133 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002134 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2135 }
2136 else {
2137 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002140 }
2141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142#ifdef TPROXY
2143 else if (!strcmp(args[0], "transparent")) {
2144 /* enable transparent proxy connections */
2145 curproxy->options |= PR_O_TRANSP;
2146 }
2147#endif
2148 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002149 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 if (*(args[1]) == 0) {
2153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 }
2157 curproxy->maxconn = atol(args[1]);
2158 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002159 else if (!strcmp(args[0], "backlog")) { /* backlog */
2160 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002162
2163 if (*(args[1]) == 0) {
2164 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002167 }
2168 curproxy->backlog = atol(args[1]);
2169 }
Willy Tarreau86034312006-12-29 00:10:33 +01002170 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002171 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173
Willy Tarreau86034312006-12-29 00:10:33 +01002174 if (*(args[1]) == 0) {
2175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002178 }
2179 curproxy->fullconn = atol(args[1]);
2180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2182 if (*(args[1]) == 0) {
2183 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002187 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2188 if (err) {
2189 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2190 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002193 }
2194 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 }
2196 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2197 if (curproxy == &defproxy) {
2198 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002203 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002204
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 if (strchr(args[1], ':') == NULL) {
2206 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
2210 curproxy->dispatch_addr = *str2sa(args[1]);
2211 }
2212 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002216 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002217 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2218 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
2223 else if (!strcmp(args[0], "server")) { /* server address */
2224 int cur_arg;
2225 char *rport;
2226 char *raddr;
2227 short realport;
2228 int do_check;
2229
2230 if (curproxy == &defproxy) {
2231 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002235 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002236 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237
2238 if (!*args[2]) {
2239 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002244
2245 err = invalid_char(args[1]);
2246 if (err) {
2247 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2248 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002251 }
2252
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_ABORT;
2256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
2258
2259 /* the servers are linked backwards first */
2260 newsrv->next = curproxy->srv;
2261 curproxy->srv = newsrv;
2262 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002263 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264
2265 LIST_INIT(&newsrv->pendconns);
2266 do_check = 0;
2267 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002268 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 newsrv->id = strdup(args[1]);
2270
2271 /* several ways to check the port component :
2272 * - IP => port=+0, relative
2273 * - IP: => port=+0, relative
2274 * - IP:N => port=N, absolute
2275 * - IP:+N => port=+N, relative
2276 * - IP:-N => port=-N, relative
2277 */
2278 raddr = strdup(args[2]);
2279 rport = strchr(raddr, ':');
2280 if (rport) {
2281 *rport++ = 0;
2282 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002283 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 newsrv->state |= SRV_MAPPORTS;
2285 } else {
2286 realport = 0;
2287 newsrv->state |= SRV_MAPPORTS;
2288 }
2289
2290 newsrv->addr = *str2sa(raddr);
2291 newsrv->addr.sin_port = htons(realport);
2292 free(raddr);
2293
2294 newsrv->curfd = -1; /* no health-check in progress */
2295 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002296 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2297 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 newsrv->rise = DEF_RISETIME;
2299 newsrv->fall = DEF_FALLTIME;
2300 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002301 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002302 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002303 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002304
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 cur_arg = 3;
2306 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002307 if (!strcmp(args[cur_arg], "id")) {
2308 struct server *target;
2309
2310 if (!*args[cur_arg + 1]) {
2311 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2312 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002315 }
2316
2317 newsrv->puid = atol(args[cur_arg + 1]);
2318
2319 if (newsrv->puid< 1001) {
2320 Alert("parsing [%s:%d]: custom id has to be > 1000",
2321 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002324 }
2325
2326 for (target = proxy->srv; target; target = target->next)
2327 if (newsrv != target && newsrv->puid == target->puid) {
2328 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2329 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002332 }
2333 cur_arg += 2;
2334 }
2335 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 newsrv->cookie = strdup(args[cur_arg + 1]);
2337 newsrv->cklen = strlen(args[cur_arg + 1]);
2338 cur_arg += 2;
2339 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002340 else if (!strcmp(args[cur_arg], "redir")) {
2341 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2342 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2343 cur_arg += 2;
2344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 else if (!strcmp(args[cur_arg], "rise")) {
2346 newsrv->rise = atol(args[cur_arg + 1]);
2347 newsrv->health = newsrv->rise;
2348 cur_arg += 2;
2349 }
2350 else if (!strcmp(args[cur_arg], "fall")) {
2351 newsrv->fall = atol(args[cur_arg + 1]);
2352 cur_arg += 2;
2353 }
2354 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002355 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2356 if (err) {
2357 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2358 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002361 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002362 if (val <= 0) {
2363 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2364 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002367 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002368 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 cur_arg += 2;
2370 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002371 else if (!strcmp(args[cur_arg], "fastinter")) {
2372 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2373 if (err) {
2374 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2375 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002378 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002379 if (val <= 0) {
2380 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2381 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002384 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002385 newsrv->fastinter = val;
2386 cur_arg += 2;
2387 }
2388 else if (!strcmp(args[cur_arg], "downinter")) {
2389 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2390 if (err) {
2391 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2392 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002395 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002396 if (val <= 0) {
2397 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2398 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002401 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002402 newsrv->downinter = val;
2403 cur_arg += 2;
2404 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002405 else if (!strcmp(args[cur_arg], "addr")) {
2406 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002407 cur_arg += 2;
2408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 else if (!strcmp(args[cur_arg], "port")) {
2410 newsrv->check_port = atol(args[cur_arg + 1]);
2411 cur_arg += 2;
2412 }
2413 else if (!strcmp(args[cur_arg], "backup")) {
2414 newsrv->state |= SRV_BACKUP;
2415 cur_arg ++;
2416 }
2417 else if (!strcmp(args[cur_arg], "weight")) {
2418 int w;
2419 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002420 if (w < 0 || w > 256) {
2421 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002426 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 cur_arg += 2;
2428 }
2429 else if (!strcmp(args[cur_arg], "minconn")) {
2430 newsrv->minconn = atol(args[cur_arg + 1]);
2431 cur_arg += 2;
2432 }
2433 else if (!strcmp(args[cur_arg], "maxconn")) {
2434 newsrv->maxconn = atol(args[cur_arg + 1]);
2435 cur_arg += 2;
2436 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002437 else if (!strcmp(args[cur_arg], "maxqueue")) {
2438 newsrv->maxqueue = atol(args[cur_arg + 1]);
2439 cur_arg += 2;
2440 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002441 else if (!strcmp(args[cur_arg], "slowstart")) {
2442 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002443 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002444 if (err) {
2445 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2446 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002449 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002450 if (val <= 0) {
2451 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2452 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002455 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002456 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002457 cur_arg += 2;
2458 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002459 else if (!strcmp(args[cur_arg], "track")) {
2460
2461 if (!*args[cur_arg + 1]) {
2462 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2463 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002466 }
2467
2468 newsrv->trackit = strdup(args[cur_arg + 1]);
2469
2470 cur_arg += 2;
2471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 else if (!strcmp(args[cur_arg], "check")) {
2473 global.maxsock++;
2474 do_check = 1;
2475 cur_arg += 1;
2476 }
2477 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002478 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002480#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002481 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002482 file, linenum, "source", "usesrc");
2483#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002484 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002486#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002491 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2492
2493 if (port_low != port_high) {
2494 int i;
2495 if (port_low <= 0 || port_low > 65535 ||
2496 port_high <= 0 || port_high > 65535 ||
2497 port_low > port_high) {
2498 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2499 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002502 }
2503 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2504 for (i = 0; i < newsrv->sport_range->size; i++)
2505 newsrv->sport_range->ports[i] = port_low + i;
2506 }
2507
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002509 while (*(args[cur_arg])) {
2510 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002511#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2512#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002513 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2514 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2515 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002518 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002519#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002520 if (!*args[cur_arg + 1]) {
2521 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2522 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002525 }
2526 if (!strcmp(args[cur_arg + 1], "client")) {
2527 newsrv->state |= SRV_TPROXY_CLI;
2528 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2529 newsrv->state |= SRV_TPROXY_CIP;
2530 } else {
2531 newsrv->state |= SRV_TPROXY_ADDR;
2532 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2533 }
2534 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002535#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002536 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002537#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002538 cur_arg += 2;
2539 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002540#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002541 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002542 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002545#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2546 } /* "usesrc" */
2547
2548 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2549#ifdef SO_BINDTODEVICE
2550 if (!*args[cur_arg + 1]) {
2551 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002555 }
2556 if (newsrv->iface_name)
2557 free(newsrv->iface_name);
2558
2559 newsrv->iface_name = strdup(args[cur_arg + 1]);
2560 newsrv->iface_len = strlen(newsrv->iface_name);
2561 global.last_checks |= LSTCHK_NETADM;
2562#else
2563 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2564 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002567#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002568 cur_arg += 2;
2569 continue;
2570 }
2571 /* this keyword in not an option of "source" */
2572 break;
2573 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002575 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2576 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2577 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002580 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002582 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 +02002583 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
2587 }
2588
2589 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002590 if (newsrv->trackit) {
2591 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002595 }
2596
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002597 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2598 newsrv->check_port = newsrv->check_addr.sin_port;
2599
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2601 newsrv->check_port = realport; /* by default */
2602 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002603 /* not yet valid, because no port was set on
2604 * the server either. We'll check if we have
2605 * a known port on the first listener.
2606 */
2607 struct listener *l;
2608 l = curproxy->listen;
2609 if (l) {
2610 int port;
2611 port = (l->addr.ss_family == AF_INET6)
2612 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2613 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2614 newsrv->check_port = port;
2615 }
2616 }
2617 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2619 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623 newsrv->state |= SRV_CHECKED;
2624 }
2625
2626 if (newsrv->state & SRV_BACKUP)
2627 curproxy->srv_bck++;
2628 else
2629 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002630
2631 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 }
2633 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002634 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 int facility;
2636
2637 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2638 curproxy->logfac1 = global.logfac1;
2639 curproxy->logsrv1 = global.logsrv1;
2640 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002641 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 curproxy->logfac2 = global.logfac2;
2643 curproxy->logsrv2 = global.logsrv2;
2644 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002645 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 }
2647 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002648 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649
2650 facility = get_log_facility(args[2]);
2651 if (facility < 0) {
2652 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2653 exit(1);
2654 }
2655
2656 level = 7; /* max syslog level = debug */
2657 if (*(args[3])) {
2658 level = get_log_level(args[3]);
2659 if (level < 0) {
2660 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2661 exit(1);
2662 }
2663 }
2664
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002665 minlvl = 0; /* limit syslog level to this level (emerg) */
2666 if (*(args[4])) {
2667 minlvl = get_log_level(args[4]);
2668 if (level < 0) {
2669 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2670 exit(1);
2671 }
2672 }
2673
Robert Tsai81ae1952007-12-05 10:47:29 +01002674 if (args[1][0] == '/') {
2675 logsrv.u.addr.sa_family = AF_UNIX;
2676 logsrv.u.un = *str2sun(args[1]);
2677 } else {
2678 logsrv.u.addr.sa_family = AF_INET;
2679 logsrv.u.in = *str2sa(args[1]);
2680 if (!logsrv.u.in.sin_port) {
2681 logsrv.u.in.sin_port =
2682 htons(SYSLOG_PORT);
2683 }
2684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685
2686 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002687 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 curproxy->logfac1 = facility;
2689 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002690 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002693 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 curproxy->logfac2 = facility;
2695 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002696 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 }
2698 else {
2699 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
2703 }
2704 else {
2705 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2706 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 }
2710 }
2711 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002712 int cur_arg;
2713
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002716
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002718 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2719 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002723
2724 /* we must first clear any optional default setting */
2725 curproxy->options &= ~PR_O_TPXY_MASK;
2726 free(curproxy->iface_name);
2727 curproxy->iface_name = NULL;
2728 curproxy->iface_len = 0;
2729
Willy Tarreaubaaee002006-06-26 02:48:02 +02002730 curproxy->source_addr = *str2sa(args[1]);
2731 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002732
2733 cur_arg = 2;
2734 while (*(args[cur_arg])) {
2735 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002736#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2737#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002738 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2739 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2740 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002743 }
2744#endif
2745 if (!*args[cur_arg + 1]) {
2746 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2747 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002750 }
2751
2752 if (!strcmp(args[cur_arg + 1], "client")) {
2753 curproxy->options |= PR_O_TPXY_CLI;
2754 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2755 curproxy->options |= PR_O_TPXY_CIP;
2756 } else {
2757 curproxy->options |= PR_O_TPXY_ADDR;
2758 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2759 }
2760 global.last_checks |= LSTCHK_NETADM;
2761#if !defined(CONFIG_HAP_LINUX_TPROXY)
2762 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002763#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002764#else /* no TPROXY support */
2765 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002766 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002769#endif
2770 cur_arg += 2;
2771 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002772 }
2773
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002774 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2775#ifdef SO_BINDTODEVICE
2776 if (!*args[cur_arg + 1]) {
2777 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002781 }
2782 if (curproxy->iface_name)
2783 free(curproxy->iface_name);
2784
2785 curproxy->iface_name = strdup(args[cur_arg + 1]);
2786 curproxy->iface_len = strlen(curproxy->iface_name);
2787 global.last_checks |= LSTCHK_NETADM;
2788#else
2789 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2790 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002793#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002794 cur_arg += 2;
2795 continue;
2796 }
2797 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2798 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002803 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2804 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2805 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2810 regex_t *preg;
2811 if (curproxy == &defproxy) {
2812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002816 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818
Willy Tarreaubaaee002006-06-26 02:48:02 +02002819 if (*(args[1]) == 0 || *(args[2]) == 0) {
2820 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824 }
2825
2826 preg = calloc(1, sizeof(regex_t));
2827 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2828 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
2832
2833 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2834 if (err) {
2835 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2836 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002837 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002839 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
2841 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2842 regex_t *preg;
2843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002848 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002850
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 if (*(args[1]) == 0) {
2852 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
2856
2857 preg = calloc(1, sizeof(regex_t));
2858 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2859 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
2863
2864 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002865 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
2867 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2868 regex_t *preg;
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002874 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002876
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 if (*(args[1]) == 0) {
2878 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 }
2882
2883 preg = calloc(1, sizeof(regex_t));
2884 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2885 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888 }
2889
2890 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002891 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 }
2893 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2894 regex_t *preg;
2895 if (curproxy == &defproxy) {
2896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002902
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 if (*(args[1]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 }
2908
2909 preg = calloc(1, sizeof(regex_t));
2910 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2911 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 }
2915
2916 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002917 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
2919 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2920 regex_t *preg;
2921 if (curproxy == &defproxy) {
2922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 if (*(args[1]) == 0) {
2930 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 }
2934
2935 preg = calloc(1, sizeof(regex_t));
2936 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2937 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002938 err_code |= ERR_ALERT | ERR_FATAL;
2939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 }
2941
2942 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002943 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002945 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2946 regex_t *preg;
2947 if (curproxy == &defproxy) {
2948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002951 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002954
Willy Tarreaub8750a82006-09-03 09:56:00 +02002955 if (*(args[1]) == 0) {
2956 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002959 }
2960
2961 preg = calloc(1, sizeof(regex_t));
2962 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2963 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002966 }
2967
2968 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002969 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002970 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002971 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2972 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002973 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002977 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002979 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01002980
Willy Tarreau977b8e42006-12-29 14:19:17 +01002981 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002982 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002986 }
2987
2988 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002989 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002990 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002993 }
2994
2995 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002996 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002997 }
2998 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2999 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003001 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003004 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003005 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003007
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003009 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003013 }
3014
3015 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003016 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003017 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003020 }
3021
3022 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003023 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3026 regex_t *preg;
3027 if (curproxy == &defproxy) {
3028 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003032 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003033 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003034
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035 if (*(args[1]) == 0 || *(args[2]) == 0) {
3036 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 }
3041
3042 preg = calloc(1, sizeof(regex_t));
3043 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3044 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 }
3048
3049 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3050 if (err) {
3051 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3052 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003056 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 }
3058 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3059 regex_t *preg;
3060 if (curproxy == &defproxy) {
3061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003065 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003067
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 if (*(args[1]) == 0) {
3069 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\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 }
3073
3074 preg = calloc(1, sizeof(regex_t));
3075 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3076 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
3080
3081 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003082 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3085 regex_t *preg;
3086 if (curproxy == &defproxy) {
3087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003091 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003093
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 if (*(args[1]) == 0) {
3095 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\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 }
3099
3100 preg = calloc(1, sizeof(regex_t));
3101 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3102 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
3106
3107 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003108 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
3110 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3111 regex_t *preg;
3112 if (curproxy == &defproxy) {
3113 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003117 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 if (*(args[1]) == 0) {
3121 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
3125
3126 preg = calloc(1, sizeof(regex_t));
3127 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3128 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
3132
3133 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003134 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3137 regex_t *preg;
3138 if (curproxy == &defproxy) {
3139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003143 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 if (*(args[1]) == 0) {
3147 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 }
3151
3152 preg = calloc(1, sizeof(regex_t));
3153 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3154 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
3158
3159 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003160 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003162 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3163 regex_t *preg;
3164 if (curproxy == &defproxy) {
3165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003169 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003171
Willy Tarreaub8750a82006-09-03 09:56:00 +02003172 if (*(args[1]) == 0) {
3173 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003176 }
3177
3178 preg = calloc(1, sizeof(regex_t));
3179 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3180 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003183 }
3184
3185 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003186 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3189 if (curproxy == &defproxy) {
3190 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003194 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196
3197 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3198 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202
3203 if (*(args[1]) == 0) {
3204 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208
3209 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003210 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3213 regex_t *preg;
3214
3215 if (*(args[1]) == 0 || *(args[2]) == 0) {
3216 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3217 file, linenum, args[0]);
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003223
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 preg = calloc(1, sizeof(regex_t));
3225 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3226 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_FATAL;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230
3231 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3232 if (err) {
3233 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3234 file, linenum, *err);
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 Tarreau61d18892009-03-31 10:49:21 +02003238 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
3240 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3241 regex_t *preg;
3242 if (curproxy == &defproxy) {
3243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003247 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003249
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 if (*(args[1]) == 0) {
3251 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 }
3255
3256 preg = calloc(1, sizeof(regex_t));
3257 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3258 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 }
3262
3263 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3264 if (err) {
3265 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3266 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
3270 }
3271 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3272 regex_t *preg;
3273 if (curproxy == &defproxy) {
3274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003278 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003280
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 if (*(args[1]) == 0) {
3282 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 }
3286
3287 preg = calloc(1, sizeof(regex_t));
3288 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3289 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293
3294 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3295 if (err) {
3296 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3297 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301 }
3302 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3303 regex_t *preg;
3304 if (curproxy == &defproxy) {
3305 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003309 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311
3312 if (*(args[1]) == 0 || *(args[2]) == 0) {
3313 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3314 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 }
3318
3319 preg = calloc(1, sizeof(regex_t));
3320 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3321 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
3325
3326 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3327 if (err) {
3328 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3329 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 }
3333 }
3334 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3335 regex_t *preg;
3336 if (curproxy == &defproxy) {
3337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003341 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003343
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 if (*(args[1]) == 0) {
3345 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
3349
3350 preg = calloc(1, sizeof(regex_t));
3351 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3352 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356
3357 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3358 if (err) {
3359 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3360 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364 }
3365 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3366 regex_t *preg;
3367 if (curproxy == &defproxy) {
3368 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003372 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003374
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 if (*(args[1]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380
3381 preg = calloc(1, sizeof(regex_t));
3382 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3383 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387
3388 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3389 if (err) {
3390 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3391 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
3395 }
3396 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3397 if (curproxy == &defproxy) {
3398 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003402 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404
3405 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3406 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
3410
3411 if (*(args[1]) == 0) {
3412 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 }
3416
3417 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3418 }
3419 else if (!strcmp(args[0], "errorloc") ||
3420 !strcmp(args[0], "errorloc302") ||
3421 !strcmp(args[0], "errorloc303")) { /* error location */
3422 int errnum, errlen;
3423 char *err;
3424
Willy Tarreau977b8e42006-12-29 14:19:17 +01003425 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003427
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003429 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
3433
3434 errnum = atol(args[1]);
3435 if (!strcmp(args[0], "errorloc303")) {
3436 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3437 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3438 } else {
3439 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3440 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3441 }
3442
Willy Tarreau0f772532006-12-23 20:51:41 +01003443 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3444 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003445 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003446 curproxy->errmsg[rc].str = err;
3447 curproxy->errmsg[rc].len = errlen;
3448 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003450 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003451
3452 if (rc >= HTTP_ERR_SIZE) {
3453 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3454 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 free(err);
3456 }
3457 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003458 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3459 int errnum, errlen, fd;
3460 char *err;
3461 struct stat stat;
3462
3463 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003465
3466 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003467 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003470 }
3471
3472 fd = open(args[2], O_RDONLY);
3473 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3474 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3475 file, linenum, args[2], args[1]);
3476 if (fd >= 0)
3477 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003480 }
3481
3482 if (stat.st_size <= BUFSIZE) {
3483 errlen = stat.st_size;
3484 } else {
3485 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3486 file, linenum, args[2], BUFSIZE);
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003488 errlen = BUFSIZE;
3489 }
3490
3491 err = malloc(errlen); /* malloc() must succeed during parsing */
3492 errnum = read(fd, err, errlen);
3493 if (errnum != errlen) {
3494 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3495 file, linenum, args[2], args[1]);
3496 close(fd);
3497 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003500 }
3501 close(fd);
3502
3503 errnum = atol(args[1]);
3504 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3505 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003506 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003507 curproxy->errmsg[rc].str = err;
3508 curproxy->errmsg[rc].len = errlen;
3509 break;
3510 }
3511 }
3512
3513 if (rc >= HTTP_ERR_SIZE) {
3514 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3515 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003517 free(err);
3518 }
3519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003521 struct cfg_kw_list *kwl;
3522 int index;
3523
3524 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3525 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3526 if (kwl->kw[index].section != CFG_LISTEN)
3527 continue;
3528 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3529 /* prepare error message just in case */
3530 snprintf(trash, sizeof(trash),
3531 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003532 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3533 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003534 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003537 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003538 else if (rc > 0) {
3539 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_WARN;
3541 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003542 }
Willy Tarreau93893792009-07-23 13:19:11 +02003543 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003544 }
3545 }
3546 }
3547
Willy Tarreau6daf3432008-01-22 16:44:08 +01003548 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 }
Willy Tarreau93893792009-07-23 13:19:11 +02003552 out:
3553 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554}
3555
3556
3557/*
3558 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003559 * Returns the error code, 0 if OK, or any combination of :
3560 * - ERR_ABORT: must abort ASAP
3561 * - ERR_FATAL: we can continue parsing but not start the service
3562 * - ERR_WARN: a warning has been emitted
3563 * - ERR_ALERT: an alert has been emitted
3564 * Only the two first ones can stop processing, the two others are just
3565 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003567int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003569 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 FILE *f;
3571 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003573 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 if ((f=fopen(file,"r")) == NULL)
3576 return -1;
3577
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003578 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003579 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003580 char *end;
3581 char *args[MAX_LINE_ARGS + 1];
3582 char *line = thisline;
3583
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 linenum++;
3585
3586 end = line + strlen(line);
3587
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003588 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3589 /* Check if we reached the limit and the last char is not \n.
3590 * Watch out for the last line without the terminating '\n'!
3591 */
3592 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003593 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003594 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003595 }
3596
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003598 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 line++;
3600
3601 arg = 0;
3602 args[arg] = line;
3603
3604 while (*line && arg < MAX_LINE_ARGS) {
3605 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3606 * C equivalent value. Other combinations left unchanged (eg: \1).
3607 */
3608 if (*line == '\\') {
3609 int skip = 0;
3610 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3611 *line = line[1];
3612 skip = 1;
3613 }
3614 else if (line[1] == 'r') {
3615 *line = '\r';
3616 skip = 1;
3617 }
3618 else if (line[1] == 'n') {
3619 *line = '\n';
3620 skip = 1;
3621 }
3622 else if (line[1] == 't') {
3623 *line = '\t';
3624 skip = 1;
3625 }
3626 else if (line[1] == 'x') {
3627 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3628 unsigned char hex1, hex2;
3629 hex1 = toupper(line[2]) - '0';
3630 hex2 = toupper(line[3]) - '0';
3631 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3632 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3633 *line = (hex1<<4) + hex2;
3634 skip = 3;
3635 }
3636 else {
3637 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 }
3640 }
3641 if (skip) {
3642 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3643 end -= skip;
3644 }
3645 line++;
3646 }
3647 else if (*line == '#' || *line == '\n' || *line == '\r') {
3648 /* end of string, end of loop */
3649 *line = 0;
3650 break;
3651 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003652 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003654 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003655 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 line++;
3657 args[++arg] = line;
3658 }
3659 else {
3660 line++;
3661 }
3662 }
3663
3664 /* empty line */
3665 if (!**args)
3666 continue;
3667
Willy Tarreau540abe42007-05-02 20:50:16 +02003668 /* zero out remaining args and ensure that at least one entry
3669 * is zeroed out.
3670 */
3671 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 args[arg] = line;
3673 }
3674
Willy Tarreau3842f002009-06-14 11:39:52 +02003675 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003676 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003677 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003678 for (arg=0; *args[arg+1]; arg++)
3679 args[arg] = args[arg+1]; // shift args after inversion
3680 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003681 else if (!strcmp(args[0], "default")) {
3682 kwm = KWM_DEF;
3683 for (arg=0; *args[arg+1]; arg++)
3684 args[arg] = args[arg+1]; // shift args after inversion
3685 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003686
Willy Tarreau3842f002009-06-14 11:39:52 +02003687 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3688 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003689 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003690 }
3691
Willy Tarreau977b8e42006-12-29 14:19:17 +01003692 if (!strcmp(args[0], "listen") ||
3693 !strcmp(args[0], "frontend") ||
3694 !strcmp(args[0], "backend") ||
3695 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003696 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003698 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003699 cursection = strdup(args[0]);
3700 }
3701 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003703 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003704 cursection = strdup(args[0]);
3705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 /* else it's a section keyword */
3707
3708 switch (confsect) {
3709 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 break;
3712 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003713 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 break;
3715 default:
3716 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003719
3720 if (err_code & ERR_ABORT)
3721 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003723 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003724 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003726 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003727}
3728
Willy Tarreaubb925012009-07-23 13:36:36 +02003729/*
3730 * 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.
3737 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003738int check_config_validity()
3739{
3740 int cfgerr = 0;
3741 struct proxy *curproxy = NULL;
3742 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003743 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744
3745 /*
3746 * Now, check for the integrity of all that we have collected.
3747 */
3748
3749 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003750 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003752 /* first, we will invert the proxy list order */
3753 curproxy = NULL;
3754 while (proxy) {
3755 struct proxy *next;
3756
3757 next = proxy->next;
3758 proxy->next = curproxy;
3759 curproxy = proxy;
3760 if (!next)
3761 break;
3762 proxy = next;
3763 }
3764
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003766 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
3770
3771 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003772 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003773 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003774
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003776 /* ensure we don't keep listeners uselessly bound */
3777 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 curproxy = curproxy->next;
3779 continue;
3780 }
3781
Willy Tarreauff01a212009-03-15 13:46:16 +01003782 switch (curproxy->mode) {
3783 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003784 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003785 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003786 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3787 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003788 cfgerr++;
3789 }
3790
3791 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003792 Warning("config : servers will be ignored for %s '%s'.\n",
3793 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003794 break;
3795
3796 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003797 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003798 break;
3799
3800 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003801 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003802 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003803 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3804 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003805 cfgerr++;
3806 }
3807 break;
3808 }
3809
3810 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003811 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3812 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 cfgerr++;
3814 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003815
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003816 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3817 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3818 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003819 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
3820 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003821 cfgerr++;
3822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003824 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003825 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3826 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003827 cfgerr++;
3828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003830 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003831 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3832 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003833 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003834 }
3835 }
3836 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3837 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3838 /* If no LB algo is set in a backend, and we're not in
3839 * transparent mode, dispatch mode nor proxy mode, we
3840 * want to use balance roundrobin by default.
3841 */
3842 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3843 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003846
Willy Tarreau82936582007-11-30 15:20:09 +01003847 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3848 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003849 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3850 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003851 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01003852 }
3853
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003854 /* if a default backend was specified, let's find it */
3855 if (curproxy->defbe.name) {
3856 struct proxy *target;
3857
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003858 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3859 if (!target) {
3860 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3861 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003862 cfgerr++;
3863 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003864 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3865 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02003866 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003867 } else {
3868 free(curproxy->defbe.name);
3869 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003870 /* we force the backend to be present on at least all of
3871 * the frontend's processes.
3872 */
3873 target->bind_proc = curproxy->bind_proc ?
3874 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
3876 }
3877
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003878 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003879 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3880 /* map jump target for ACT_SETBE in req_rep chain */
3881 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003882 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003883 struct proxy *target;
3884
Willy Tarreaua496b602006-12-17 23:15:24 +01003885 if (exp->action != ACT_SETBE)
3886 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003887
3888 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3889 if (!target) {
3890 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3891 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003892 cfgerr++;
3893 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003894 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3895 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003896 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003897 } else {
3898 free((void *)exp->replace);
3899 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003900 /* we force the backend to be present on at least all of
3901 * the frontend's processes.
3902 */
3903 target->bind_proc = curproxy->bind_proc ?
3904 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003905 }
3906 }
3907 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003908
3909 /* find the target proxy for 'use_backend' rules */
3910 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003911 struct proxy *target;
3912
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003913 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003914
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003915 if (!target) {
3916 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3917 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003918 cfgerr++;
3919 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003920 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3921 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003922 cfgerr++;
3923 } else {
3924 free((void *)rule->be.name);
3925 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003926 /* we force the backend to be present on at least all of
3927 * the frontend's processes.
3928 */
3929 target->bind_proc = curproxy->bind_proc ?
3930 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003931 }
3932 }
3933
Willy Tarreau2738a142006-07-08 17:28:09 +02003934 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003935 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003936 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003937 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003938 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003939 " | While not properly invalid, you will certainly encounter various problems\n"
3940 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003941 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003942 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003943 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02003944 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003945
Willy Tarreau1fa31262007-12-03 00:36:16 +01003946 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3947 * We must still support older configurations, so let's find out whether those
3948 * parameters have been set or must be copied from contimeouts.
3949 */
3950 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003951 if (!curproxy->timeout.tarpit ||
3952 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003953 /* tarpit timeout not set. We search in the following order:
3954 * default.tarpit, curr.connect, default.connect.
3955 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003956 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003957 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003958 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003959 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003960 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003961 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003962 }
3963 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003964 (!curproxy->timeout.queue ||
3965 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003966 /* queue timeout not set. We search in the following order:
3967 * default.queue, curr.connect, default.connect.
3968 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003969 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003970 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003971 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003972 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003973 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003974 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003975 }
3976 }
3977
Willy Tarreauf3c69202006-07-09 16:42:34 +02003978 if (curproxy->options & PR_O_SSL3_CHK) {
3979 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3980 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3981 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3982 }
3983
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003984 /* The small pools required for the capture lists */
3985 if (curproxy->nb_req_cap)
3986 curproxy->req_cap_pool = create_pool("ptrcap",
3987 curproxy->nb_req_cap * sizeof(char *),
3988 MEM_F_SHARED);
3989 if (curproxy->nb_rsp_cap)
3990 curproxy->rsp_cap_pool = create_pool("ptrcap",
3991 curproxy->nb_rsp_cap * sizeof(char *),
3992 MEM_F_SHARED);
3993
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003994 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3995 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3996 MEM_F_SHARED);
3997
Willy Tarreau86034312006-12-29 00:10:33 +01003998 /* for backwards compatibility with "listen" instances, if
3999 * fullconn is not set but maxconn is set, then maxconn
4000 * is used.
4001 */
4002 if (!curproxy->fullconn)
4003 curproxy->fullconn = curproxy->maxconn;
4004
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 /* first, we will invert the servers list order */
4006 newsrv = NULL;
4007 while (curproxy->srv) {
4008 struct server *next;
4009
4010 next = curproxy->srv->next;
4011 curproxy->srv->next = newsrv;
4012 newsrv = curproxy->srv;
4013 if (!next)
4014 break;
4015 curproxy->srv = next;
4016 }
4017
Willy Tarreau20697042007-11-15 23:26:18 +01004018 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004019 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020
Willy Tarreaub625a082007-11-26 01:15:43 +01004021 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01004022 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01004023 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01004024 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
4025 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01004026 else
4027 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028
4029 if (curproxy->options & PR_O_LOGASAP)
4030 curproxy->to_log &= ~LW_BYTES;
4031
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004032 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4033 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4034 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4035 proxy_type_str(curproxy), curproxy->id);
4036 err_code |= ERR_WARN;
4037 }
4038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004040 * ensure that we're not cross-dressing a TCP server into HTTP.
4041 */
4042 newsrv = curproxy->srv;
4043 while (newsrv != NULL) {
4044 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004045 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4046 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004047 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004048 }
4049 newsrv = newsrv->next;
4050 }
4051
4052 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 * If this server supports a maxconn parameter, it needs a dedicated
4054 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004055 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 */
4057 newsrv = curproxy->srv;
4058 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004059 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 /* Only 'minconn' was specified, or it was higher than or equal
4061 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4062 * this will avoid further useless expensive computations.
4063 */
4064 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004065 } else if (newsrv->maxconn && !newsrv->minconn) {
4066 /* minconn was not specified, so we set it to maxconn */
4067 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004068 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004069 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4070 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004071 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 }
4073
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004074 if (newsrv->trackit) {
4075 struct proxy *px;
4076 struct server *srv;
4077 char *pname, *sname;
4078
4079 pname = newsrv->trackit;
4080 sname = strrchr(pname, '/');
4081
4082 if (sname)
4083 *sname++ = '\0';
4084 else {
4085 sname = pname;
4086 pname = NULL;
4087 }
4088
4089 if (pname) {
4090 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4091 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004092 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4093 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004094 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004095 cfgerr++;
4096 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004097 }
4098 } else
4099 px = curproxy;
4100
4101 srv = findserver(px, sname);
4102 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004103 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4104 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004105 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004106 cfgerr++;
4107 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004108 }
4109
4110 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004111 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004112 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004113 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004114 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004115 cfgerr++;
4116 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004117 }
4118
4119 if (curproxy != px &&
4120 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004121 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004122 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004123 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004124 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004125 cfgerr++;
4126 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004127 }
4128
4129 newsrv->tracked = srv;
4130 newsrv->tracknext = srv->tracknext;
4131 srv->tracknext = newsrv;
4132
4133 free(newsrv->trackit);
4134 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004135 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 newsrv = newsrv->next;
4137 }
4138
Willy Tarreaue6b98942007-10-29 01:09:36 +01004139 /* adjust this proxy's listeners */
4140 listener = curproxy->listen;
4141 while (listener) {
4142 if (curproxy->options & PR_O_TCP_NOLING)
4143 listener->options |= LI_O_NOLINGER;
4144 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004145 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004146 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004147 listener->accept = event_accept;
4148 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004149 listener->handler = process_session;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004150 /* both TCP and HTTP must check switching rules */
4151 listener->analysers |= AN_REQ_SWITCHING_RULES;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004152
4153 if (curproxy->mode == PR_MODE_HTTP)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004154 listener->analysers |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004155
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004156 /* smart accept mode is automatic in HTTP mode */
4157 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4158 (curproxy->mode == PR_MODE_HTTP &&
4159 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4160 listener->options |= LI_O_NOQUICKACK;
4161
Willy Tarreaud869b242009-03-15 14:43:58 +01004162 if (curproxy->tcp_req.inspect_delay ||
4163 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01004164 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004165
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004166 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004167 listener = listener->next;
4168 }
4169
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 curproxy = curproxy->next;
4171 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004172
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004173 /*
4174 * Recount currently required checks.
4175 */
4176
4177 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4178 int optnum;
4179
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004180 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4181 if (curproxy->options & cfg_opts[optnum].val)
4182 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004183
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004184 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4185 if (curproxy->options2 & cfg_opts2[optnum].val)
4186 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004187 }
4188
Willy Tarreaubb925012009-07-23 13:36:36 +02004189 if (cfgerr > 0)
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 out:
4192 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193}
4194
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004195/*
4196 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4197 * parsing sessions.
4198 */
4199void cfg_register_keywords(struct cfg_kw_list *kwl)
4200{
4201 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4202}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004204/*
4205 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4206 */
4207void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4208{
4209 LIST_DEL(&kwl->list);
4210 LIST_INIT(&kwl->list);
4211}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212
4213/*
4214 * Local variables:
4215 * c-indent-level: 8
4216 * c-basic-offset: 8
4217 * End:
4218 */