blob: 8b3d3f1839577e8eeba7687f57d52b24f96c639d [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) {
Willy Tarreau1d45b7c2009-08-16 10:29:18 +02001728 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'node-name', '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 Tarreau1d45b7c2009-08-16 10:29:18 +02001751 } else if (!strcmp(args[1], "node-name")) {
1752 if (!stats_set_node_name(&curproxy->uri_auth, *(args[2]) ? args[2] : hostname)) {
1753 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1754 err_code |= ERR_ALERT | ERR_ABORT;
1755 goto out;
1756 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001757 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001758 unsigned interval;
1759
1760 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1761 if (err) {
1762 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1763 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001766 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1767 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001768 err_code |= ERR_ALERT | ERR_ABORT;
1769 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 } else if (!strcmp(args[1], "auth")) {
1772 if (*(args[2]) == 0) {
1773 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1777 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001778 err_code |= ERR_ALERT | ERR_ABORT;
1779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 }
1781 } else if (!strcmp(args[1], "scope")) {
1782 if (*(args[2]) == 0) {
1783 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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 }
1791 } else if (!strcmp(args[1], "enable")) {
1792 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001797 } else if (!strcmp(args[1], "hide-version")) {
1798 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1799 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001800 err_code |= ERR_ALERT | ERR_ABORT;
1801 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001804 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 }
1809 }
1810 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001811 int optnum;
1812
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001813 if (*(args[1]) == '\0') {
1814 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1815 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001819
1820 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1821 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001822 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1823 err_code |= ERR_WARN;
1824 goto out;
1825 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001826
Willy Tarreau3842f002009-06-14 11:39:52 +02001827 curproxy->no_options &= ~cfg_opts[optnum].val;
1828 curproxy->options &= ~cfg_opts[optnum].val;
1829
1830 switch (kwm) {
1831 case KWM_STD:
1832 curproxy->options |= cfg_opts[optnum].val;
1833 break;
1834 case KWM_NO:
1835 curproxy->no_options |= cfg_opts[optnum].val;
1836 break;
1837 case KWM_DEF: /* already cleared */
1838 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001839 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001840
Willy Tarreau93893792009-07-23 13:19:11 +02001841 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001842 }
1843 }
1844
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001845 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1846 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001847 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1848 err_code |= ERR_WARN;
1849 goto out;
1850 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001851
Willy Tarreau3842f002009-06-14 11:39:52 +02001852 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1853 curproxy->options2 &= ~cfg_opts2[optnum].val;
1854
1855 switch (kwm) {
1856 case KWM_STD:
1857 curproxy->options2 |= cfg_opts2[optnum].val;
1858 break;
1859 case KWM_NO:
1860 curproxy->no_options2 |= cfg_opts2[optnum].val;
1861 break;
1862 case KWM_DEF: /* already cleared */
1863 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001864 }
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001866 }
1867 }
1868
Willy Tarreau3842f002009-06-14 11:39:52 +02001869 if (kwm != KWM_STD) {
1870 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001871 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001872 err_code |= ERR_ALERT | ERR_FATAL;
1873 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001874 }
1875
Emeric Brun3a058f32009-06-30 18:26:00 +02001876 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02001878 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02001880 if (*(args[2]) != '\0') {
1881 if (!strcmp(args[2], "clf")) {
1882 curproxy->options2 |= PR_O2_CLFLOG;
1883 } else {
1884 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02001887 }
1888 }
1889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 else if (!strcmp(args[1], "tcplog"))
1891 /* generate a detailed TCP log */
1892 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 else if (!strcmp(args[1], "tcpka")) {
1894 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001895 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001897
1898 if (curproxy->cap & PR_CAP_FE)
1899 curproxy->options |= PR_O_TCP_CLI_KA;
1900 if (curproxy->cap & PR_CAP_BE)
1901 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 }
1903 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001904 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_WARN;
1906
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001909 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001910 curproxy->options &= ~PR_O_SMTP_CHK;
1911 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 if (!*args[2]) { /* no argument */
1913 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1914 curproxy->check_len = strlen(DEF_CHECK_REQ);
1915 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001916 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 curproxy->check_req = (char *)malloc(reqlen);
1918 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1919 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1920 } else { /* more arguments : METHOD URI [HTTP_VER] */
1921 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1922 if (*args[4])
1923 reqlen += strlen(args[4]);
1924 else
1925 reqlen += strlen("HTTP/1.0");
1926
1927 curproxy->check_req = (char *)malloc(reqlen);
1928 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1929 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1930 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001931 }
1932 else if (!strcmp(args[1], "ssl-hello-chk")) {
1933 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001934 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001938 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001939 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001940 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 }
Willy Tarreau23677902007-05-08 23:50:35 +02001942 else if (!strcmp(args[1], "smtpchk")) {
1943 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001944 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001945 curproxy->options &= ~PR_O_HTTP_CHK;
1946 curproxy->options &= ~PR_O_SSL3_CHK;
1947 curproxy->options |= PR_O_SMTP_CHK;
1948
1949 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1950 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1951 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1952 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1953 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1954 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1955 curproxy->check_req = (char *)malloc(reqlen);
1956 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1957 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1958 } else {
1959 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1960 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1961 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1962 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1963 }
1964 }
1965 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001966 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001967 int cur_arg;
1968
1969 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1970 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001971 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001972
1973 curproxy->options |= PR_O_FWDFOR;
1974
1975 free(curproxy->fwdfor_hdr_name);
1976 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1977 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1978
1979 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1980 cur_arg = 2;
1981 while (*(args[cur_arg])) {
1982 if (!strcmp(args[cur_arg], "except")) {
1983 /* suboption except - needs additional argument for it */
1984 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1985 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1986 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_ALERT | ERR_FATAL;
1988 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001989 }
1990 /* flush useless bits */
1991 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001992 cur_arg += 2;
1993 } else if (!strcmp(args[cur_arg], "header")) {
1994 /* suboption header - needs additional argument for it */
1995 if (*(args[cur_arg+1]) == 0) {
1996 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1997 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002000 }
2001 free(curproxy->fwdfor_hdr_name);
2002 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2003 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2004 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002005 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002006 /* unknown suboption - catchall */
2007 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2008 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002011 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002012 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002013 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002014 else if (!strcmp(args[1], "originalto")) {
2015 int cur_arg;
2016
2017 /* insert x-original-to field, but not for the IP address listed as an except.
2018 * set default options (ie: bitfield, header name, etc)
2019 */
2020
2021 curproxy->options |= PR_O_ORGTO;
2022
2023 free(curproxy->orgto_hdr_name);
2024 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2025 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2026
2027 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2028 cur_arg = 2;
2029 while (*(args[cur_arg])) {
2030 if (!strcmp(args[cur_arg], "except")) {
2031 /* suboption except - needs additional argument for it */
2032 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2033 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2034 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002037 }
2038 /* flush useless bits */
2039 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2040 cur_arg += 2;
2041 } else if (!strcmp(args[cur_arg], "header")) {
2042 /* suboption header - needs additional argument for it */
2043 if (*(args[cur_arg+1]) == 0) {
2044 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2045 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002048 }
2049 free(curproxy->orgto_hdr_name);
2050 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2051 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2052 cur_arg += 2;
2053 } else {
2054 /* unknown suboption - catchall */
2055 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2056 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002059 }
2060 } /* end while loop */
2061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 else {
2063 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 }
Willy Tarreau93893792009-07-23 13:19:11 +02002067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002069 else if (!strcmp(args[0], "default_backend")) {
2070 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002072
2073 if (*(args[1]) == 0) {
2074 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002077 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002078 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002079 curproxy->defbe.name = strdup(args[1]);
2080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002082 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002084
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002085 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2086 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 /* enable reconnections to dispatch */
2089 curproxy->options |= PR_O_REDISP;
2090 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002091 else if (!strcmp(args[0], "http-check")) {
2092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002094
2095 if (strcmp(args[1], "disable-on-404") == 0) {
2096 /* enable a graceful server shutdown on an HTTP 404 response */
2097 curproxy->options |= PR_O_DISABLE404;
2098 }
2099 else {
2100 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002103 }
2104 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002105 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002106 if (curproxy == &defproxy) {
2107 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002110 }
2111
Willy Tarreaub80c2302007-11-30 20:51:32 +01002112 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002114
2115 if (strcmp(args[1], "fail") == 0) {
2116 /* add a condition to fail monitor requests */
2117 int pol = ACL_COND_NONE;
2118 struct acl_cond *cond;
2119
2120 if (!strcmp(args[2], "if"))
2121 pol = ACL_COND_IF;
2122 else if (!strcmp(args[2], "unless"))
2123 pol = ACL_COND_UNLESS;
2124
2125 if (pol == ACL_COND_NONE) {
2126 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2127 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002130 }
2131
2132 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2133 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2134 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002137 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002138 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002139 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002140 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2141 }
2142 else {
2143 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002146 }
2147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148#ifdef TPROXY
2149 else if (!strcmp(args[0], "transparent")) {
2150 /* enable transparent proxy connections */
2151 curproxy->options |= PR_O_TRANSP;
2152 }
2153#endif
2154 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 if (*(args[1]) == 0) {
2159 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
2163 curproxy->maxconn = atol(args[1]);
2164 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002165 else if (!strcmp(args[0], "backlog")) { /* backlog */
2166 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002167 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002168
2169 if (*(args[1]) == 0) {
2170 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_ALERT | ERR_FATAL;
2172 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002173 }
2174 curproxy->backlog = atol(args[1]);
2175 }
Willy Tarreau86034312006-12-29 00:10:33 +01002176 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002177 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002178 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002179
Willy Tarreau86034312006-12-29 00:10:33 +01002180 if (*(args[1]) == 0) {
2181 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002184 }
2185 curproxy->fullconn = atol(args[1]);
2186 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2188 if (*(args[1]) == 0) {
2189 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002193 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2194 if (err) {
2195 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2196 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002199 }
2200 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 }
2202 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2203 if (curproxy == &defproxy) {
2204 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 if (strchr(args[1], ':') == NULL) {
2212 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 }
2216 curproxy->dispatch_addr = *str2sa(args[1]);
2217 }
2218 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002222 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002223 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2224 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 }
2229 else if (!strcmp(args[0], "server")) { /* server address */
2230 int cur_arg;
2231 char *rport;
2232 char *raddr;
2233 short realport;
2234 int do_check;
2235
2236 if (curproxy == &defproxy) {
2237 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243
2244 if (!*args[2]) {
2245 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002250
2251 err = invalid_char(args[1]);
2252 if (err) {
2253 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2254 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002257 }
2258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2260 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_ABORT;
2262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
2264
2265 /* the servers are linked backwards first */
2266 newsrv->next = curproxy->srv;
2267 curproxy->srv = newsrv;
2268 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002269 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270
2271 LIST_INIT(&newsrv->pendconns);
2272 do_check = 0;
2273 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002274 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 newsrv->id = strdup(args[1]);
2276
2277 /* several ways to check the port component :
2278 * - IP => port=+0, relative
2279 * - IP: => port=+0, relative
2280 * - IP:N => port=N, absolute
2281 * - IP:+N => port=+N, relative
2282 * - IP:-N => port=-N, relative
2283 */
2284 raddr = strdup(args[2]);
2285 rport = strchr(raddr, ':');
2286 if (rport) {
2287 *rport++ = 0;
2288 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002289 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 newsrv->state |= SRV_MAPPORTS;
2291 } else {
2292 realport = 0;
2293 newsrv->state |= SRV_MAPPORTS;
2294 }
2295
2296 newsrv->addr = *str2sa(raddr);
2297 newsrv->addr.sin_port = htons(realport);
2298 free(raddr);
2299
2300 newsrv->curfd = -1; /* no health-check in progress */
2301 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002302 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2303 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 newsrv->rise = DEF_RISETIME;
2305 newsrv->fall = DEF_FALLTIME;
2306 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002307 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002308 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002309 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002310
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 cur_arg = 3;
2312 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002313 if (!strcmp(args[cur_arg], "id")) {
2314 struct server *target;
2315
2316 if (!*args[cur_arg + 1]) {
2317 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2318 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002321 }
2322
2323 newsrv->puid = atol(args[cur_arg + 1]);
2324
2325 if (newsrv->puid< 1001) {
2326 Alert("parsing [%s:%d]: custom id has to be > 1000",
2327 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002330 }
2331
2332 for (target = proxy->srv; target; target = target->next)
2333 if (newsrv != target && newsrv->puid == target->puid) {
2334 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2335 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002338 }
2339 cur_arg += 2;
2340 }
2341 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 newsrv->cookie = strdup(args[cur_arg + 1]);
2343 newsrv->cklen = strlen(args[cur_arg + 1]);
2344 cur_arg += 2;
2345 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002346 else if (!strcmp(args[cur_arg], "redir")) {
2347 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2348 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2349 cur_arg += 2;
2350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 else if (!strcmp(args[cur_arg], "rise")) {
2352 newsrv->rise = atol(args[cur_arg + 1]);
2353 newsrv->health = newsrv->rise;
2354 cur_arg += 2;
2355 }
2356 else if (!strcmp(args[cur_arg], "fall")) {
2357 newsrv->fall = atol(args[cur_arg + 1]);
2358 cur_arg += 2;
2359 }
2360 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002361 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2362 if (err) {
2363 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2364 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002367 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002368 if (val <= 0) {
2369 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2370 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002373 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002374 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 cur_arg += 2;
2376 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002377 else if (!strcmp(args[cur_arg], "fastinter")) {
2378 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2379 if (err) {
2380 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2381 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002384 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002385 if (val <= 0) {
2386 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2387 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002390 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002391 newsrv->fastinter = val;
2392 cur_arg += 2;
2393 }
2394 else if (!strcmp(args[cur_arg], "downinter")) {
2395 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2396 if (err) {
2397 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2398 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002401 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002402 if (val <= 0) {
2403 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2404 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002407 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002408 newsrv->downinter = val;
2409 cur_arg += 2;
2410 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002411 else if (!strcmp(args[cur_arg], "addr")) {
2412 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002413 cur_arg += 2;
2414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 else if (!strcmp(args[cur_arg], "port")) {
2416 newsrv->check_port = atol(args[cur_arg + 1]);
2417 cur_arg += 2;
2418 }
2419 else if (!strcmp(args[cur_arg], "backup")) {
2420 newsrv->state |= SRV_BACKUP;
2421 cur_arg ++;
2422 }
2423 else if (!strcmp(args[cur_arg], "weight")) {
2424 int w;
2425 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002426 if (w < 0 || w > 256) {
2427 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002432 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 cur_arg += 2;
2434 }
2435 else if (!strcmp(args[cur_arg], "minconn")) {
2436 newsrv->minconn = atol(args[cur_arg + 1]);
2437 cur_arg += 2;
2438 }
2439 else if (!strcmp(args[cur_arg], "maxconn")) {
2440 newsrv->maxconn = atol(args[cur_arg + 1]);
2441 cur_arg += 2;
2442 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002443 else if (!strcmp(args[cur_arg], "maxqueue")) {
2444 newsrv->maxqueue = atol(args[cur_arg + 1]);
2445 cur_arg += 2;
2446 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002447 else if (!strcmp(args[cur_arg], "slowstart")) {
2448 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002449 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002450 if (err) {
2451 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2452 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002455 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002456 if (val <= 0) {
2457 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2458 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002461 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002462 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002463 cur_arg += 2;
2464 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002465 else if (!strcmp(args[cur_arg], "track")) {
2466
2467 if (!*args[cur_arg + 1]) {
2468 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2469 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002472 }
2473
2474 newsrv->trackit = strdup(args[cur_arg + 1]);
2475
2476 cur_arg += 2;
2477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 else if (!strcmp(args[cur_arg], "check")) {
2479 global.maxsock++;
2480 do_check = 1;
2481 cur_arg += 1;
2482 }
2483 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002484 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002486#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002488 file, linenum, "source", "usesrc");
2489#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002490 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002492#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
2496 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002497 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2498
2499 if (port_low != port_high) {
2500 int i;
2501 if (port_low <= 0 || port_low > 65535 ||
2502 port_high <= 0 || port_high > 65535 ||
2503 port_low > port_high) {
2504 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2505 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002508 }
2509 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2510 for (i = 0; i < newsrv->sport_range->size; i++)
2511 newsrv->sport_range->ports[i] = port_low + i;
2512 }
2513
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002515 while (*(args[cur_arg])) {
2516 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002517#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2518#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002519 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2520 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2521 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002524 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002525#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002526 if (!*args[cur_arg + 1]) {
2527 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2528 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002531 }
2532 if (!strcmp(args[cur_arg + 1], "client")) {
2533 newsrv->state |= SRV_TPROXY_CLI;
2534 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2535 newsrv->state |= SRV_TPROXY_CIP;
2536 } else {
2537 newsrv->state |= SRV_TPROXY_ADDR;
2538 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2539 }
2540 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002541#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002542 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002543#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002544 cur_arg += 2;
2545 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002546#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002547 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002548 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002551#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2552 } /* "usesrc" */
2553
2554 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2555#ifdef SO_BINDTODEVICE
2556 if (!*args[cur_arg + 1]) {
2557 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2558 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002561 }
2562 if (newsrv->iface_name)
2563 free(newsrv->iface_name);
2564
2565 newsrv->iface_name = strdup(args[cur_arg + 1]);
2566 newsrv->iface_len = strlen(newsrv->iface_name);
2567 global.last_checks |= LSTCHK_NETADM;
2568#else
2569 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2570 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002573#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002574 cur_arg += 2;
2575 continue;
2576 }
2577 /* this keyword in not an option of "source" */
2578 break;
2579 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002581 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2582 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2583 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002588 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 +02002589 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
2593 }
2594
2595 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002596 if (newsrv->trackit) {
2597 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2598 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002601 }
2602
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002603 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2604 newsrv->check_port = newsrv->check_addr.sin_port;
2605
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2607 newsrv->check_port = realport; /* by default */
2608 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002609 /* not yet valid, because no port was set on
2610 * the server either. We'll check if we have
2611 * a known port on the first listener.
2612 */
2613 struct listener *l;
2614 l = curproxy->listen;
2615 if (l) {
2616 int port;
2617 port = (l->addr.ss_family == AF_INET6)
2618 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2619 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2620 newsrv->check_port = port;
2621 }
2622 }
2623 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2625 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 }
2629 newsrv->state |= SRV_CHECKED;
2630 }
2631
2632 if (newsrv->state & SRV_BACKUP)
2633 curproxy->srv_bck++;
2634 else
2635 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002636
2637 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 }
2639 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002640 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 int facility;
2642
2643 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2644 curproxy->logfac1 = global.logfac1;
2645 curproxy->logsrv1 = global.logsrv1;
2646 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002647 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 curproxy->logfac2 = global.logfac2;
2649 curproxy->logsrv2 = global.logsrv2;
2650 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002651 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652 }
2653 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002654 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655
2656 facility = get_log_facility(args[2]);
2657 if (facility < 0) {
2658 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2659 exit(1);
2660 }
2661
2662 level = 7; /* max syslog level = debug */
2663 if (*(args[3])) {
2664 level = get_log_level(args[3]);
2665 if (level < 0) {
2666 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2667 exit(1);
2668 }
2669 }
2670
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002671 minlvl = 0; /* limit syslog level to this level (emerg) */
2672 if (*(args[4])) {
2673 minlvl = get_log_level(args[4]);
2674 if (level < 0) {
2675 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2676 exit(1);
2677 }
2678 }
2679
Robert Tsai81ae1952007-12-05 10:47:29 +01002680 if (args[1][0] == '/') {
2681 logsrv.u.addr.sa_family = AF_UNIX;
2682 logsrv.u.un = *str2sun(args[1]);
2683 } else {
2684 logsrv.u.addr.sa_family = AF_INET;
2685 logsrv.u.in = *str2sa(args[1]);
2686 if (!logsrv.u.in.sin_port) {
2687 logsrv.u.in.sin_port =
2688 htons(SYSLOG_PORT);
2689 }
2690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691
2692 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002693 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 curproxy->logfac1 = facility;
2695 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002696 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 }
2698 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002699 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 curproxy->logfac2 = facility;
2701 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002702 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
2704 else {
2705 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 }
2709 }
2710 else {
2711 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2712 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715 }
2716 }
2717 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002718 int cur_arg;
2719
Willy Tarreau977b8e42006-12-29 14:19:17 +01002720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002722
Willy Tarreaubaaee002006-06-26 02:48:02 +02002723 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002724 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2725 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002729
2730 /* we must first clear any optional default setting */
2731 curproxy->options &= ~PR_O_TPXY_MASK;
2732 free(curproxy->iface_name);
2733 curproxy->iface_name = NULL;
2734 curproxy->iface_len = 0;
2735
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 curproxy->source_addr = *str2sa(args[1]);
2737 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002738
2739 cur_arg = 2;
2740 while (*(args[cur_arg])) {
2741 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002742#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2743#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002744 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2745 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2746 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002749 }
2750#endif
2751 if (!*args[cur_arg + 1]) {
2752 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2753 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002756 }
2757
2758 if (!strcmp(args[cur_arg + 1], "client")) {
2759 curproxy->options |= PR_O_TPXY_CLI;
2760 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2761 curproxy->options |= PR_O_TPXY_CIP;
2762 } else {
2763 curproxy->options |= PR_O_TPXY_ADDR;
2764 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2765 }
2766 global.last_checks |= LSTCHK_NETADM;
2767#if !defined(CONFIG_HAP_LINUX_TPROXY)
2768 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002769#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002770#else /* no TPROXY support */
2771 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002772 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002775#endif
2776 cur_arg += 2;
2777 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002778 }
2779
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002780 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2781#ifdef SO_BINDTODEVICE
2782 if (!*args[cur_arg + 1]) {
2783 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002787 }
2788 if (curproxy->iface_name)
2789 free(curproxy->iface_name);
2790
2791 curproxy->iface_name = strdup(args[cur_arg + 1]);
2792 curproxy->iface_len = strlen(curproxy->iface_name);
2793 global.last_checks |= LSTCHK_NETADM;
2794#else
2795 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2796 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002799#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002800 cur_arg += 2;
2801 continue;
2802 }
2803 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2804 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002809 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2810 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2811 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2816 regex_t *preg;
2817 if (curproxy == &defproxy) {
2818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002822 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002824
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 if (*(args[1]) == 0 || *(args[2]) == 0) {
2826 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2827 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 }
2831
2832 preg = calloc(1, sizeof(regex_t));
2833 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2834 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 }
2838
2839 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2840 if (err) {
2841 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2842 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002845 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002846 }
2847 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2848 regex_t *preg;
2849 if (curproxy == &defproxy) {
2850 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002856
Willy Tarreaubaaee002006-06-26 02:48:02 +02002857 if (*(args[1]) == 0) {
2858 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
2862
2863 preg = calloc(1, sizeof(regex_t));
2864 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2865 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868 }
2869
2870 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002871 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 }
2873 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2874 regex_t *preg;
2875 if (curproxy == &defproxy) {
2876 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002880 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002881 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002882
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 if (*(args[1]) == 0) {
2884 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 }
2888
2889 preg = calloc(1, sizeof(regex_t));
2890 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2891 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 }
2895
2896 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002897 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898 }
2899 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2900 regex_t *preg;
2901 if (curproxy == &defproxy) {
2902 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002907 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if (*(args[1]) == 0) {
2910 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 }
2914
2915 preg = calloc(1, sizeof(regex_t));
2916 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2917 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920 }
2921
2922 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002923 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 }
2925 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2926 regex_t *preg;
2927 if (curproxy == &defproxy) {
2928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002932 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935 if (*(args[1]) == 0) {
2936 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002939 }
2940
2941 preg = calloc(1, sizeof(regex_t));
2942 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2943 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 }
2947
2948 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002949 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002951 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2952 regex_t *preg;
2953 if (curproxy == &defproxy) {
2954 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002958 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002960
Willy Tarreaub8750a82006-09-03 09:56:00 +02002961 if (*(args[1]) == 0) {
2962 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002965 }
2966
2967 preg = calloc(1, sizeof(regex_t));
2968 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2969 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002972 }
2973
2974 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002975 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002976 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002977 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2978 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002979 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002980 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01002986
Willy Tarreau977b8e42006-12-29 14:19:17 +01002987 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002988 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2989 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002992 }
2993
2994 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002995 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002996 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002999 }
3000
3001 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003002 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003003 }
3004 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3005 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003006 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003010 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003011 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003013
Willy Tarreau977b8e42006-12-29 14:19:17 +01003014 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003015 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003019 }
3020
3021 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003022 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003023 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003026 }
3027
3028 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003029 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3032 regex_t *preg;
3033 if (curproxy == &defproxy) {
3034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003038 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003040
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 if (*(args[1]) == 0 || *(args[2]) == 0) {
3042 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3043 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 }
3047
3048 preg = calloc(1, sizeof(regex_t));
3049 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3050 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 }
3054
3055 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3056 if (err) {
3057 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3058 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003062 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3065 regex_t *preg;
3066 if (curproxy == &defproxy) {
3067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003071 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 if (*(args[1]) == 0) {
3075 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 }
3079
3080 preg = calloc(1, sizeof(regex_t));
3081 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3082 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
3086
3087 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003088 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 }
3090 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3091 regex_t *preg;
3092 if (curproxy == &defproxy) {
3093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003097 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003099
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 if (*(args[1]) == 0) {
3101 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 }
3105
3106 preg = calloc(1, sizeof(regex_t));
3107 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3108 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 }
3112
3113 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003114 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 }
3116 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3117 regex_t *preg;
3118 if (curproxy == &defproxy) {
3119 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003123 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003125
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 if (*(args[1]) == 0) {
3127 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 }
3131
3132 preg = calloc(1, sizeof(regex_t));
3133 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3134 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 }
3138
3139 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003140 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 }
3142 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3143 regex_t *preg;
3144 if (curproxy == &defproxy) {
3145 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003149 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003151
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 if (*(args[1]) == 0) {
3153 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
3157
3158 preg = calloc(1, sizeof(regex_t));
3159 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3160 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 }
3164
3165 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003166 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003168 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3169 regex_t *preg;
3170 if (curproxy == &defproxy) {
3171 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003174 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003175 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003177
Willy Tarreaub8750a82006-09-03 09:56:00 +02003178 if (*(args[1]) == 0) {
3179 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003182 }
3183
3184 preg = calloc(1, sizeof(regex_t));
3185 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3186 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003189 }
3190
3191 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003192 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3195 if (curproxy == &defproxy) {
3196 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003200 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202
3203 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3204 Alert("parsing [%s:%d] : too many '%s'. Continuing.\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 if (*(args[1]) == 0) {
3210 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
3214
3215 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003216 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3219 regex_t *preg;
3220
3221 if (*(args[1]) == 0 || *(args[2]) == 0) {
3222 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003227 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 preg = calloc(1, sizeof(regex_t));
3231 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3232 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
3236
3237 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3238 if (err) {
3239 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3240 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003244 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
3246 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3247 regex_t *preg;
3248 if (curproxy == &defproxy) {
3249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003253 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003255
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 if (*(args[1]) == 0) {
3257 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261
3262 preg = calloc(1, sizeof(regex_t));
3263 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3264 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 }
3268
3269 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3270 if (err) {
3271 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3272 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276 }
3277 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3278 regex_t *preg;
3279 if (curproxy == &defproxy) {
3280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003284 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 if (*(args[1]) == 0) {
3288 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
3292
3293 preg = calloc(1, sizeof(regex_t));
3294 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3295 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299
3300 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3301 if (err) {
3302 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3303 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
3307 }
3308 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3309 regex_t *preg;
3310 if (curproxy == &defproxy) {
3311 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003315 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317
3318 if (*(args[1]) == 0 || *(args[2]) == 0) {
3319 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
3324
3325 preg = calloc(1, sizeof(regex_t));
3326 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3327 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331
3332 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3333 if (err) {
3334 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3335 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
3339 }
3340 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3341 regex_t *preg;
3342 if (curproxy == &defproxy) {
3343 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003347 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003349
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 if (*(args[1]) == 0) {
3351 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 }
3355
3356 preg = calloc(1, sizeof(regex_t));
3357 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3358 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003359 err_code |= ERR_ALERT | ERR_FATAL;
3360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 }
3362
3363 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3364 if (err) {
3365 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3366 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 }
3370 }
3371 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3372 regex_t *preg;
3373 if (curproxy == &defproxy) {
3374 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003378 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003380
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 if (*(args[1]) == 0) {
3382 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 }
3386
3387 preg = calloc(1, sizeof(regex_t));
3388 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3389 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
3393
3394 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3395 if (err) {
3396 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3397 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401 }
3402 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3403 if (curproxy == &defproxy) {
3404 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003408 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410
3411 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3412 Alert("parsing [%s:%d] : too many '%s'. Continuing.\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 if (*(args[1]) == 0) {
3418 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
3422
3423 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3424 }
3425 else if (!strcmp(args[0], "errorloc") ||
3426 !strcmp(args[0], "errorloc302") ||
3427 !strcmp(args[0], "errorloc303")) { /* error location */
3428 int errnum, errlen;
3429 char *err;
3430
Willy Tarreau977b8e42006-12-29 14:19:17 +01003431 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003433
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003435 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
3439
3440 errnum = atol(args[1]);
3441 if (!strcmp(args[0], "errorloc303")) {
3442 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3443 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3444 } else {
3445 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3446 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3447 }
3448
Willy Tarreau0f772532006-12-23 20:51:41 +01003449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3450 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003451 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003452 curproxy->errmsg[rc].str = err;
3453 curproxy->errmsg[rc].len = errlen;
3454 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003457
3458 if (rc >= HTTP_ERR_SIZE) {
3459 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3460 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 free(err);
3462 }
3463 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003464 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3465 int errnum, errlen, fd;
3466 char *err;
3467 struct stat stat;
3468
3469 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003471
3472 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003473 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003476 }
3477
3478 fd = open(args[2], O_RDONLY);
3479 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3480 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3481 file, linenum, args[2], args[1]);
3482 if (fd >= 0)
3483 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003486 }
3487
3488 if (stat.st_size <= BUFSIZE) {
3489 errlen = stat.st_size;
3490 } else {
3491 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3492 file, linenum, args[2], BUFSIZE);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003494 errlen = BUFSIZE;
3495 }
3496
3497 err = malloc(errlen); /* malloc() must succeed during parsing */
3498 errnum = read(fd, err, errlen);
3499 if (errnum != errlen) {
3500 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3501 file, linenum, args[2], args[1]);
3502 close(fd);
3503 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003506 }
3507 close(fd);
3508
3509 errnum = atol(args[1]);
3510 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3511 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003512 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003513 curproxy->errmsg[rc].str = err;
3514 curproxy->errmsg[rc].len = errlen;
3515 break;
3516 }
3517 }
3518
3519 if (rc >= HTTP_ERR_SIZE) {
3520 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3521 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003522 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003523 free(err);
3524 }
3525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003526 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003527 struct cfg_kw_list *kwl;
3528 int index;
3529
3530 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3531 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3532 if (kwl->kw[index].section != CFG_LISTEN)
3533 continue;
3534 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3535 /* prepare error message just in case */
3536 snprintf(trash, sizeof(trash),
3537 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003538 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3539 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003540 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003543 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003544 else if (rc > 0) {
3545 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_WARN;
3547 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003548 }
Willy Tarreau93893792009-07-23 13:19:11 +02003549 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003550 }
3551 }
3552 }
3553
Willy Tarreau6daf3432008-01-22 16:44:08 +01003554 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
Willy Tarreau93893792009-07-23 13:19:11 +02003558 out:
3559 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560}
3561
3562
3563/*
3564 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003565 * Returns the error code, 0 if OK, or any combination of :
3566 * - ERR_ABORT: must abort ASAP
3567 * - ERR_FATAL: we can continue parsing but not start the service
3568 * - ERR_WARN: a warning has been emitted
3569 * - ERR_ALERT: an alert has been emitted
3570 * Only the two first ones can stop processing, the two others are just
3571 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003573int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003575 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 FILE *f;
3577 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003579 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580
Willy Tarreaubaaee002006-06-26 02:48:02 +02003581 if ((f=fopen(file,"r")) == NULL)
3582 return -1;
3583
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003584 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003585 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003586 char *end;
3587 char *args[MAX_LINE_ARGS + 1];
3588 char *line = thisline;
3589
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 linenum++;
3591
3592 end = line + strlen(line);
3593
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003594 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3595 /* Check if we reached the limit and the last char is not \n.
3596 * Watch out for the last line without the terminating '\n'!
3597 */
3598 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003599 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003601 }
3602
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003604 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 line++;
3606
3607 arg = 0;
3608 args[arg] = line;
3609
3610 while (*line && arg < MAX_LINE_ARGS) {
3611 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3612 * C equivalent value. Other combinations left unchanged (eg: \1).
3613 */
3614 if (*line == '\\') {
3615 int skip = 0;
3616 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3617 *line = line[1];
3618 skip = 1;
3619 }
3620 else if (line[1] == 'r') {
3621 *line = '\r';
3622 skip = 1;
3623 }
3624 else if (line[1] == 'n') {
3625 *line = '\n';
3626 skip = 1;
3627 }
3628 else if (line[1] == 't') {
3629 *line = '\t';
3630 skip = 1;
3631 }
3632 else if (line[1] == 'x') {
3633 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3634 unsigned char hex1, hex2;
3635 hex1 = toupper(line[2]) - '0';
3636 hex2 = toupper(line[3]) - '0';
3637 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3638 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3639 *line = (hex1<<4) + hex2;
3640 skip = 3;
3641 }
3642 else {
3643 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
3646 }
3647 if (skip) {
3648 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3649 end -= skip;
3650 }
3651 line++;
3652 }
3653 else if (*line == '#' || *line == '\n' || *line == '\r') {
3654 /* end of string, end of loop */
3655 *line = 0;
3656 break;
3657 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003658 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003660 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003661 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 line++;
3663 args[++arg] = line;
3664 }
3665 else {
3666 line++;
3667 }
3668 }
3669
3670 /* empty line */
3671 if (!**args)
3672 continue;
3673
Willy Tarreau540abe42007-05-02 20:50:16 +02003674 /* zero out remaining args and ensure that at least one entry
3675 * is zeroed out.
3676 */
3677 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 args[arg] = line;
3679 }
3680
Willy Tarreau3842f002009-06-14 11:39:52 +02003681 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003682 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003683 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003684 for (arg=0; *args[arg+1]; arg++)
3685 args[arg] = args[arg+1]; // shift args after inversion
3686 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003687 else if (!strcmp(args[0], "default")) {
3688 kwm = KWM_DEF;
3689 for (arg=0; *args[arg+1]; arg++)
3690 args[arg] = args[arg+1]; // shift args after inversion
3691 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003692
Willy Tarreau3842f002009-06-14 11:39:52 +02003693 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3694 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003696 }
3697
Willy Tarreau977b8e42006-12-29 14:19:17 +01003698 if (!strcmp(args[0], "listen") ||
3699 !strcmp(args[0], "frontend") ||
3700 !strcmp(args[0], "backend") ||
3701 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003702 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003703 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003704 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003705 cursection = strdup(args[0]);
3706 }
3707 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003709 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003710 cursection = strdup(args[0]);
3711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 /* else it's a section keyword */
3713
3714 switch (confsect) {
3715 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 break;
3718 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003719 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 break;
3721 default:
3722 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003725
3726 if (err_code & ERR_ABORT)
3727 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003729 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003730 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003732 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003733}
3734
Willy Tarreaubb925012009-07-23 13:36:36 +02003735/*
3736 * Returns the error code, 0 if OK, or any combination of :
3737 * - ERR_ABORT: must abort ASAP
3738 * - ERR_FATAL: we can continue parsing but not start the service
3739 * - ERR_WARN: a warning has been emitted
3740 * - ERR_ALERT: an alert has been emitted
3741 * Only the two first ones can stop processing, the two others are just
3742 * indicators.
3743 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003744int check_config_validity()
3745{
3746 int cfgerr = 0;
3747 struct proxy *curproxy = NULL;
3748 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003749 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750
3751 /*
3752 * Now, check for the integrity of all that we have collected.
3753 */
3754
3755 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003756 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003758 /* first, we will invert the proxy list order */
3759 curproxy = NULL;
3760 while (proxy) {
3761 struct proxy *next;
3762
3763 next = proxy->next;
3764 proxy->next = curproxy;
3765 curproxy = proxy;
3766 if (!next)
3767 break;
3768 proxy = next;
3769 }
3770
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003772 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 }
3776
3777 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003778 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003779 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003780
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003782 /* ensure we don't keep listeners uselessly bound */
3783 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 curproxy = curproxy->next;
3785 continue;
3786 }
3787
Willy Tarreauff01a212009-03-15 13:46:16 +01003788 switch (curproxy->mode) {
3789 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003790 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003791 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003792 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3793 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003794 cfgerr++;
3795 }
3796
3797 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003798 Warning("config : servers will be ignored for %s '%s'.\n",
3799 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003800 break;
3801
3802 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003803 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003804 break;
3805
3806 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003807 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003808 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003809 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3810 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003811 cfgerr++;
3812 }
3813 break;
3814 }
3815
3816 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003817 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3818 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 cfgerr++;
3820 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003821
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003822 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3823 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3824 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003825 Alert("config : %s '%s' cannot use both transparent and 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#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003830 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003831 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3832 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003833 cfgerr++;
3834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003836 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003837 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3838 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003839 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003840 }
3841 }
3842 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3843 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3844 /* If no LB algo is set in a backend, and we're not in
3845 * transparent mode, dispatch mode nor proxy mode, we
3846 * want to use balance roundrobin by default.
3847 */
3848 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3849 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003852
Willy Tarreau82936582007-11-30 15:20:09 +01003853 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3854 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003855 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3856 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003857 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01003858 }
3859
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003860 /* if a default backend was specified, let's find it */
3861 if (curproxy->defbe.name) {
3862 struct proxy *target;
3863
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003864 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3865 if (!target) {
3866 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3867 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003868 cfgerr++;
3869 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003870 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3871 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02003872 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003873 } else {
3874 free(curproxy->defbe.name);
3875 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003876 /* we force the backend to be present on at least all of
3877 * the frontend's processes.
3878 */
3879 target->bind_proc = curproxy->bind_proc ?
3880 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
3882 }
3883
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003884 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003885 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3886 /* map jump target for ACT_SETBE in req_rep chain */
3887 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003888 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003889 struct proxy *target;
3890
Willy Tarreaua496b602006-12-17 23:15:24 +01003891 if (exp->action != ACT_SETBE)
3892 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003893
3894 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3895 if (!target) {
3896 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3897 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003898 cfgerr++;
3899 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003900 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3901 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003903 } else {
3904 free((void *)exp->replace);
3905 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003906 /* we force the backend to be present on at least all of
3907 * the frontend's processes.
3908 */
3909 target->bind_proc = curproxy->bind_proc ?
3910 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003911 }
3912 }
3913 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003914
3915 /* find the target proxy for 'use_backend' rules */
3916 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003917 struct proxy *target;
3918
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003919 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003920
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003921 if (!target) {
3922 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3923 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003924 cfgerr++;
3925 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003926 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3927 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003928 cfgerr++;
3929 } else {
3930 free((void *)rule->be.name);
3931 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003932 /* we force the backend to be present on at least all of
3933 * the frontend's processes.
3934 */
3935 target->bind_proc = curproxy->bind_proc ?
3936 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003937 }
3938 }
3939
Willy Tarreau2738a142006-07-08 17:28:09 +02003940 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003941 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003942 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003943 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003944 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003945 " | While not properly invalid, you will certainly encounter various problems\n"
3946 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003947 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003948 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003949 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02003950 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003951
Willy Tarreau1fa31262007-12-03 00:36:16 +01003952 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3953 * We must still support older configurations, so let's find out whether those
3954 * parameters have been set or must be copied from contimeouts.
3955 */
3956 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003957 if (!curproxy->timeout.tarpit ||
3958 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003959 /* tarpit timeout not set. We search in the following order:
3960 * default.tarpit, curr.connect, default.connect.
3961 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003962 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003963 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003964 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003965 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003966 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003967 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003968 }
3969 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003970 (!curproxy->timeout.queue ||
3971 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003972 /* queue timeout not set. We search in the following order:
3973 * default.queue, curr.connect, default.connect.
3974 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003975 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003976 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003977 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003978 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003979 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003980 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003981 }
3982 }
3983
Willy Tarreauf3c69202006-07-09 16:42:34 +02003984 if (curproxy->options & PR_O_SSL3_CHK) {
3985 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3986 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3987 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3988 }
3989
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003990 /* The small pools required for the capture lists */
3991 if (curproxy->nb_req_cap)
3992 curproxy->req_cap_pool = create_pool("ptrcap",
3993 curproxy->nb_req_cap * sizeof(char *),
3994 MEM_F_SHARED);
3995 if (curproxy->nb_rsp_cap)
3996 curproxy->rsp_cap_pool = create_pool("ptrcap",
3997 curproxy->nb_rsp_cap * sizeof(char *),
3998 MEM_F_SHARED);
3999
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004000 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4001 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4002 MEM_F_SHARED);
4003
Willy Tarreau86034312006-12-29 00:10:33 +01004004 /* for backwards compatibility with "listen" instances, if
4005 * fullconn is not set but maxconn is set, then maxconn
4006 * is used.
4007 */
4008 if (!curproxy->fullconn)
4009 curproxy->fullconn = curproxy->maxconn;
4010
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 /* first, we will invert the servers list order */
4012 newsrv = NULL;
4013 while (curproxy->srv) {
4014 struct server *next;
4015
4016 next = curproxy->srv->next;
4017 curproxy->srv->next = newsrv;
4018 newsrv = curproxy->srv;
4019 if (!next)
4020 break;
4021 curproxy->srv = next;
4022 }
4023
Willy Tarreau20697042007-11-15 23:26:18 +01004024 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004025 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026
Willy Tarreaub625a082007-11-26 01:15:43 +01004027 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01004028 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01004029 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01004030 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
4031 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01004032 else
4033 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034
4035 if (curproxy->options & PR_O_LOGASAP)
4036 curproxy->to_log &= ~LW_BYTES;
4037
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004038 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4039 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4040 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4041 proxy_type_str(curproxy), curproxy->id);
4042 err_code |= ERR_WARN;
4043 }
4044
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004046 * ensure that we're not cross-dressing a TCP server into HTTP.
4047 */
4048 newsrv = curproxy->srv;
4049 while (newsrv != NULL) {
4050 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004051 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4052 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004053 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004054 }
4055 newsrv = newsrv->next;
4056 }
4057
4058 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 * If this server supports a maxconn parameter, it needs a dedicated
4060 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004061 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 */
4063 newsrv = curproxy->srv;
4064 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004065 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 /* Only 'minconn' was specified, or it was higher than or equal
4067 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4068 * this will avoid further useless expensive computations.
4069 */
4070 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004071 } else if (newsrv->maxconn && !newsrv->minconn) {
4072 /* minconn was not specified, so we set it to maxconn */
4073 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004074 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004075 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4076 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004077 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 }
4079
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004080 if (newsrv->trackit) {
4081 struct proxy *px;
4082 struct server *srv;
4083 char *pname, *sname;
4084
4085 pname = newsrv->trackit;
4086 sname = strrchr(pname, '/');
4087
4088 if (sname)
4089 *sname++ = '\0';
4090 else {
4091 sname = pname;
4092 pname = NULL;
4093 }
4094
4095 if (pname) {
4096 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4097 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004098 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4099 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004100 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004101 cfgerr++;
4102 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004103 }
4104 } else
4105 px = curproxy;
4106
4107 srv = findserver(px, sname);
4108 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004109 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4110 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004111 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004112 cfgerr++;
4113 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004114 }
4115
4116 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004117 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004118 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004119 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004120 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004121 cfgerr++;
4122 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004123 }
4124
4125 if (curproxy != px &&
4126 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004127 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004128 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004129 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004130 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004131 cfgerr++;
4132 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004133 }
4134
4135 newsrv->tracked = srv;
4136 newsrv->tracknext = srv->tracknext;
4137 srv->tracknext = newsrv;
4138
4139 free(newsrv->trackit);
4140 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004141 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 newsrv = newsrv->next;
4143 }
4144
Willy Tarreaue6b98942007-10-29 01:09:36 +01004145 /* adjust this proxy's listeners */
4146 listener = curproxy->listen;
4147 while (listener) {
4148 if (curproxy->options & PR_O_TCP_NOLING)
4149 listener->options |= LI_O_NOLINGER;
4150 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004151 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004152 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004153 listener->accept = event_accept;
4154 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004155 listener->handler = process_session;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004156 /* both TCP and HTTP must check switching rules */
4157 listener->analysers |= AN_REQ_SWITCHING_RULES;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004158
4159 if (curproxy->mode == PR_MODE_HTTP)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004160 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 +01004161
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004162 /* smart accept mode is automatic in HTTP mode */
4163 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4164 (curproxy->mode == PR_MODE_HTTP &&
4165 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4166 listener->options |= LI_O_NOQUICKACK;
4167
Willy Tarreaud869b242009-03-15 14:43:58 +01004168 if (curproxy->tcp_req.inspect_delay ||
4169 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01004170 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004171
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004172 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004173 listener = listener->next;
4174 }
4175
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 curproxy = curproxy->next;
4177 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004178
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004179 /*
4180 * Recount currently required checks.
4181 */
4182
4183 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4184 int optnum;
4185
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004186 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4187 if (curproxy->options & cfg_opts[optnum].val)
4188 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004189
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004190 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4191 if (curproxy->options2 & cfg_opts2[optnum].val)
4192 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004193 }
4194
Willy Tarreaubb925012009-07-23 13:36:36 +02004195 if (cfgerr > 0)
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 out:
4198 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199}
4200
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004201/*
4202 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4203 * parsing sessions.
4204 */
4205void cfg_register_keywords(struct cfg_kw_list *kwl)
4206{
4207 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4208}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004210/*
4211 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4212 */
4213void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4214{
4215 LIST_DEL(&kwl->list);
4216 LIST_INIT(&kwl->list);
4217}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218
4219/*
4220 * Local variables:
4221 * c-indent-level: 8
4222 * c-basic-offset: 8
4223 * End:
4224 */