blob: ce6b266b892852c8c7694065e809fcf98c5b28e0 [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>
30#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
36#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037
Willy Tarreaueb0c6142007-05-07 00:53:22 +020038#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010040#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020042#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020045#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010046#include <proto/protocols.h>
47#include <proto/proto_tcp.h>
48#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010049#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010051#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/task.h>
53
54
Willy Tarreauf3c69202006-07-09 16:42:34 +020055/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
56 * ssl-hello-chk option to ensure that the remote server speaks SSL.
57 *
58 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
59 */
60const char sslv3_client_hello_pkt[] = {
61 "\x16" /* ContentType : 0x16 = Hanshake */
62 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
63 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
64 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
65 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
66 "\x03\x00" /* Hello Version : 0x0300 = v3 */
67 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
68 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
69 "\x00" /* Session ID length : empty (no session ID) */
70 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
71 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
72 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
73 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
74 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
75 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
76 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
77 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
78 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
79 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
80 "\x00\x38" "\x00\x39" "\x00\x3A"
81 "\x01" /* Compression Length : 0x01 = 1 byte for types */
82 "\x00" /* Compression Type : 0x00 = NULL compression */
83};
84
Willy Tarreau3842f002009-06-14 11:39:52 +020085/* various keyword modifiers */
86enum kw_mod {
87 KWM_STD = 0, /* normal */
88 KWM_NO, /* "no" prefixed before the keyword */
89 KWM_DEF, /* "default" prefixed before the keyword */
90};
91
Willy Tarreau13943ab2006-12-31 00:24:10 +010092/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010093struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010094 const char *name;
95 unsigned int val;
96 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010097 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010098};
99
100/* proxy->options */
101static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100102{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100103 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100104 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100107 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
108 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
109 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
110 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
111 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
112 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
113 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
114 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100115 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100116 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
117 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100118#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100119 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
120#endif
121#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100122 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100123#endif
124
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100125 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100126};
127
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100128/* proxy->options2 */
129static const struct cfg_opt cfg_opts2[] =
130{
131#ifdef CONFIG_HAP_LINUX_SPLICE
132 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
133 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
134 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
135#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200136 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
137 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200138 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
139 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200140 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200141 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142 { NULL, 0, 0, 0 }
143};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144
Willy Tarreau6daf3432008-01-22 16:44:08 +0100145static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
147int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100148int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200149
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200150/* List head of all known configuration keywords */
151static struct cfg_kw_list cfg_keywords = {
152 .list = LIST_HEAD_INIT(cfg_keywords.list)
153};
154
Willy Tarreaubaaee002006-06-26 02:48:02 +0200155/*
156 * converts <str> to a list of listeners which are dynamically allocated.
157 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
158 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
159 * - <port> is a numerical port from 1 to 65535 ;
160 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
161 * This can be repeated as many times as necessary, separated by a coma.
162 * The <tail> argument is a pointer to a current list which should be appended
163 * to the tail of the new list. The pointer to the new list is returned.
164 */
165static struct listener *str2listener(char *str, struct listener *tail)
166{
167 struct listener *l;
168 char *c, *next, *range, *dupstr;
169 int port, end;
170
171 next = dupstr = strdup(str);
172
173 while (next && *next) {
174 struct sockaddr_storage ss;
175
176 str = next;
177 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100178 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179 *next++ = 0;
180 }
181
182 /* 2) look for the addr/port delimiter, it's the last colon. */
183 if ((range = strrchr(str, ':')) == NULL) {
184 Alert("Missing port number: '%s'\n", str);
185 goto fail;
186 }
187
188 *range++ = 0;
189
190 if (strrchr(str, ':') != NULL) {
191 /* IPv6 address contains ':' */
192 memset(&ss, 0, sizeof(ss));
193 ss.ss_family = AF_INET6;
194
195 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
196 Alert("Invalid server address: '%s'\n", str);
197 goto fail;
198 }
199 }
200 else {
201 memset(&ss, 0, sizeof(ss));
202 ss.ss_family = AF_INET;
203
204 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
205 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
206 }
207 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
208 struct hostent *he;
209
210 if ((he = gethostbyname(str)) == NULL) {
211 Alert("Invalid server name: '%s'\n", str);
212 goto fail;
213 }
214 else
215 ((struct sockaddr_in *)&ss)->sin_addr =
216 *(struct in_addr *) *(he->h_addr_list);
217 }
218 }
219
220 /* 3) look for the port-end delimiter */
221 if ((c = strchr(range, '-')) != NULL) {
222 *c++ = 0;
223 end = atol(c);
224 }
225 else {
226 end = atol(range);
227 }
228
229 port = atol(range);
230
231 if (port < 1 || port > 65535) {
232 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
237 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
238 goto fail;
239 }
240
241 for (; port <= end; port++) {
242 l = (struct listener *)calloc(1, sizeof(struct listener));
243 l->next = tail;
244 tail = l;
245
246 l->fd = -1;
247 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100248 l->state = LI_INIT;
249
250 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100252 tcpv6_add_listener(l);
253 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100255 tcpv4_add_listener(l);
256 }
257 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 } /* end for(port) */
259 } /* end while(next) */
260 free(dupstr);
261 return tail;
262 fail:
263 free(dupstr);
264 return NULL;
265}
266
Willy Tarreau977b8e42006-12-29 14:19:17 +0100267/*
268 * Sends a warning if proxy <proxy> does not have at least one of the
269 * capabilities in <cap>. An optionnal <hint> may be added at the end
270 * of the warning to help the user. Returns 1 if a warning was emitted
271 * or 0 if the condition is valid.
272 */
273int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
274{
275 char *msg;
276
277 switch (cap) {
278 case PR_CAP_BE: msg = "no backend"; break;
279 case PR_CAP_FE: msg = "no frontend"; break;
280 case PR_CAP_RS: msg = "no ruleset"; break;
281 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
282 default: msg = "not enough"; break;
283 }
284
285 if (!(proxy->cap & cap)) {
286 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100287 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100288 return 1;
289 }
290 return 0;
291}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau61d18892009-03-31 10:49:21 +0200293/* Report a warning if a rule is placed after a 'block' rule.
294 * Return 1 if the warning has been emitted, otherwise 0.
295 */
296int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
297{
298 if (!LIST_ISEMPTY(&proxy->block_cond)) {
299 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
300 file, line, arg);
301 return 1;
302 }
303 return 0;
304}
305
306/* Report a warning if a rule is placed after a reqrewrite rule.
307 * Return 1 if the warning has been emitted, otherwise 0.
308 */
309int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
310{
311 if (proxy->req_exp) {
312 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
313 file, line, arg);
314 return 1;
315 }
316 return 0;
317}
318
319/* Report a warning if a rule is placed after a reqadd rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
322int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
323{
324 if (proxy->nb_reqadd) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a redirect rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
335int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
336{
337 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a 'use_backend' rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
348int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
349{
350 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* report a warning if a block rule is dangerously placed */
359int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
360{
361 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
362 warnif_rule_after_reqadd(proxy, file, line, arg) ||
363 warnif_rule_after_redirect(proxy, file, line, arg) ||
364 warnif_rule_after_use_backend(proxy, file, line, arg);
365}
366
367/* report a warning if a reqxxx rule is dangerously placed */
368int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
369{
370 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
371 warnif_rule_after_redirect(proxy, file, line, arg) ||
372 warnif_rule_after_use_backend(proxy, file, line, arg);
373}
374
375/* report a warning if a reqadd rule is dangerously placed */
376int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
377{
378 return warnif_rule_after_redirect(proxy, file, line, arg) ||
379 warnif_rule_after_use_backend(proxy, file, line, arg);
380}
381
Willy Tarreaubaaee002006-06-26 02:48:02 +0200382/*
383 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
384 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200385int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200386{
387
388 if (!strcmp(args[0], "global")) { /* new section */
389 /* no option, nothing special to do */
390 return 0;
391 }
392 else if (!strcmp(args[0], "daemon")) {
393 global.mode |= MODE_DAEMON;
394 }
395 else if (!strcmp(args[0], "debug")) {
396 global.mode |= MODE_DEBUG;
397 }
398 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100399 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200400 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200401 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100402 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200403 }
404 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100405 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200406 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200407 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100408 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200409 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100410 else if (!strcmp(args[0], "nosplice")) {
411 global.tune.options &= ~GTUNE_USE_SPLICE;
412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200413 else if (!strcmp(args[0], "quiet")) {
414 global.mode |= MODE_QUIET;
415 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200416 else if (!strcmp(args[0], "tune.maxpollevents")) {
417 if (global.tune.maxpollevents != 0) {
418 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
419 return 0;
420 }
421 if (*(args[1]) == 0) {
422 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
423 return -1;
424 }
425 global.tune.maxpollevents = atol(args[1]);
426 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100427 else if (!strcmp(args[0], "tune.maxaccept")) {
428 if (global.tune.maxaccept != 0) {
429 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
430 return 0;
431 }
432 if (*(args[1]) == 0) {
433 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
434 return -1;
435 }
436 global.tune.maxaccept = atol(args[1]);
437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438 else if (!strcmp(args[0], "uid")) {
439 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200440 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441 return 0;
442 }
443 if (*(args[1]) == 0) {
444 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
445 return -1;
446 }
447 global.uid = atol(args[1]);
448 }
449 else if (!strcmp(args[0], "gid")) {
450 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200451 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 return 0;
453 }
454 if (*(args[1]) == 0) {
455 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
456 return -1;
457 }
458 global.gid = atol(args[1]);
459 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200460 /* user/group name handling */
461 else if (!strcmp(args[0], "user")) {
462 struct passwd *ha_user;
463 if (global.uid != 0) {
464 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
465 return 0;
466 }
467 errno = 0;
468 ha_user = getpwnam(args[1]);
469 if (ha_user != NULL) {
470 global.uid = (int)ha_user->pw_uid;
471 }
472 else {
473 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
474 exit(1);
475 }
476 }
477 else if (!strcmp(args[0], "group")) {
478 struct group *ha_group;
479 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200480 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200481 return 0;
482 }
483 errno = 0;
484 ha_group = getgrnam(args[1]);
485 if (ha_group != NULL) {
486 global.gid = (int)ha_group->gr_gid;
487 }
488 else {
489 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
490 exit(1);
491 }
492 }
493 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 else if (!strcmp(args[0], "nbproc")) {
495 if (global.nbproc != 0) {
496 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
497 return 0;
498 }
499 if (*(args[1]) == 0) {
500 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
501 return -1;
502 }
503 global.nbproc = atol(args[1]);
504 }
505 else if (!strcmp(args[0], "maxconn")) {
506 if (global.maxconn != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
508 return 0;
509 }
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
512 return -1;
513 }
514 global.maxconn = atol(args[1]);
515#ifdef SYSTEM_MAXCONN
516 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
517 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);
518 global.maxconn = DEFAULT_MAXCONN;
519 }
520#endif /* SYSTEM_MAXCONN */
521 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100522 else if (!strcmp(args[0], "maxpipes")) {
523 if (global.maxpipes != 0) {
524 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
525 return 0;
526 }
527 if (*(args[1]) == 0) {
528 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
529 return -1;
530 }
531 global.maxpipes = atol(args[1]);
532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533 else if (!strcmp(args[0], "ulimit-n")) {
534 if (global.rlimit_nofile != 0) {
535 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
536 return 0;
537 }
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 return -1;
541 }
542 global.rlimit_nofile = atol(args[1]);
543 }
544 else if (!strcmp(args[0], "chroot")) {
545 if (global.chroot != NULL) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
547 return 0;
548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
551 return -1;
552 }
553 global.chroot = strdup(args[1]);
554 }
555 else if (!strcmp(args[0], "pidfile")) {
556 if (global.pidfile != NULL) {
557 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
558 return 0;
559 }
560 if (*(args[1]) == 0) {
561 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
562 return -1;
563 }
564 global.pidfile = strdup(args[1]);
565 }
566 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100567 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200568 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569
570 if (*(args[1]) == 0 || *(args[2]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
572 return -1;
573 }
574
575 facility = get_log_facility(args[2]);
576 if (facility < 0) {
577 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
578 exit(1);
579 }
580
581 level = 7; /* max syslog level = debug */
582 if (*(args[3])) {
583 level = get_log_level(args[3]);
584 if (level < 0) {
585 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
586 exit(1);
587 }
588 }
589
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200590 minlvl = 0; /* limit syslog level to this level (emerg) */
591 if (*(args[4])) {
592 minlvl = get_log_level(args[4]);
593 if (level < 0) {
594 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
595 exit(1);
596 }
597 }
598
Robert Tsai81ae1952007-12-05 10:47:29 +0100599 if (args[1][0] == '/') {
600 logsrv.u.addr.sa_family = AF_UNIX;
601 logsrv.u.un = *str2sun(args[1]);
602 } else {
603 logsrv.u.addr.sa_family = AF_INET;
604 logsrv.u.in = *str2sa(args[1]);
605 if (!logsrv.u.in.sin_port)
606 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608
609 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100610 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 global.logfac1 = facility;
612 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200613 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 }
615 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100616 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 global.logfac2 = facility;
618 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200619 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620 }
621 else {
622 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
623 return -1;
624 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200625 }
626 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
627 if (global.spread_checks != 0) {
628 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
629 return 0;
630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
633 return -1;
634 }
635 global.spread_checks = atol(args[1]);
636 if (global.spread_checks < 0 || global.spread_checks > 50) {
637 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
638 return -1;
639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 }
641 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200642 struct cfg_kw_list *kwl;
643 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200644 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200645
646 list_for_each_entry(kwl, &cfg_keywords.list, list) {
647 for (index = 0; kwl->kw[index].kw != NULL; index++) {
648 if (kwl->kw[index].section != CFG_GLOBAL)
649 continue;
650 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
651 /* prepare error message just in case */
652 snprintf(trash, sizeof(trash),
653 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200654 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
655 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200656 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
657 return -1;
658 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200659 else if (rc > 0) {
660 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
661 return 0;
662 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200663 return 0;
664 }
665 }
666 }
667
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
669 return -1;
670 }
671 return 0;
672}
673
674
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200675void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676{
677 memset(&defproxy, 0, sizeof(defproxy));
678 defproxy.mode = PR_MODE_TCP;
679 defproxy.state = PR_STNEW;
680 defproxy.maxconn = cfg_maxpconn;
681 defproxy.conn_retries = CONN_RETRIES;
682 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200683
684 LIST_INIT(&defproxy.pendconns);
685 LIST_INIT(&defproxy.acl);
686 LIST_INIT(&defproxy.block_cond);
687 LIST_INIT(&defproxy.mon_fail_cond);
688 LIST_INIT(&defproxy.switching_rules);
689
Willy Tarreau3a70f942008-02-15 11:15:34 +0100690 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691}
692
693/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100694 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
695 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200697int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698{
699 static struct proxy *curproxy = NULL;
700 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200701 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100702 int rc;
703 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704
Willy Tarreau977b8e42006-12-29 14:19:17 +0100705 if (!strcmp(args[0], "listen"))
706 rc = PR_CAP_LISTEN;
707 else if (!strcmp(args[0], "frontend"))
708 rc = PR_CAP_FE | PR_CAP_RS;
709 else if (!strcmp(args[0], "backend"))
710 rc = PR_CAP_BE | PR_CAP_RS;
711 else if (!strcmp(args[0], "ruleset"))
712 rc = PR_CAP_RS;
713 else
714 rc = PR_CAP_NONE;
715
716 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200717 if (!*args[1]) {
718 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
719 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
720 file, linenum, args[0]);
721 return -1;
722 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200723
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100724 err = invalid_char(args[1]);
725 if (err) {
726 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
727 file, linenum, *err, args[0], args[1]);
728 return -1;
729 }
730
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200731 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
732 /*
733 * If there are two proxies with the same name only following
734 * combinations are allowed:
735 *
736 * listen backend frontend ruleset
737 * listen - - - -
738 * backend - - OK -
739 * frontend - OK - -
740 * ruleset - - - -
741 */
742
743 if (!strcmp(curproxy->id, args[1]) &&
744 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
745 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100746 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
747 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200748 }
749 }
750
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
752 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
753 return -1;
754 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100755
Willy Tarreaubaaee002006-06-26 02:48:02 +0200756 curproxy->next = proxy;
757 proxy = curproxy;
758 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200759 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200760 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200761 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100762 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200763 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200764 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765
Willy Tarreauee991362007-05-14 14:37:50 +0200766 /* Timeouts are defined as -1, so we cannot use the zeroed area
767 * as a default value.
768 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100769 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200770
771 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100773 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200774
775 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100776 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 curproxy->listen = str2listener(args[2], curproxy->listen);
778 if (!curproxy->listen)
779 return -1;
780 global.maxsock++;
781 }
782
783 /* set default values */
784 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100786 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200787 curproxy->no_options = defproxy.no_options;
788 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100789 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100790 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200791 curproxy->except_net = defproxy.except_net;
792 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200793 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200794 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200795
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200796 if (defproxy.fwdfor_hdr_len) {
797 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
798 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
799 }
800
Willy Tarreau977b8e42006-12-29 14:19:17 +0100801 if (curproxy->cap & PR_CAP_FE) {
802 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100803 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200804 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805
806 /* initialize error relocations */
807 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
808 if (defproxy.errmsg[rc].str)
809 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
810 }
811
812 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814
Willy Tarreau977b8e42006-12-29 14:19:17 +0100815 if (curproxy->cap & PR_CAP_BE) {
816 curproxy->fullconn = defproxy.fullconn;
817 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818
Willy Tarreau977b8e42006-12-29 14:19:17 +0100819 if (defproxy.check_req)
820 curproxy->check_req = strdup(defproxy.check_req);
821 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 if (defproxy.cookie_name)
824 curproxy->cookie_name = strdup(defproxy.cookie_name);
825 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100826
827 if (defproxy.url_param_name)
828 curproxy->url_param_name = strdup(defproxy.url_param_name);
829 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100830
Benoitaffb4812009-03-25 13:02:10 +0100831 if (defproxy.hh_name)
832 curproxy->hh_name = strdup(defproxy.hh_name);
833 curproxy->hh_len = defproxy.hh_len;
834 curproxy->hh_match_domain = defproxy.hh_match_domain;
835
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100836 if (defproxy.iface_name)
837 curproxy->iface_name = strdup(defproxy.iface_name);
838 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840
Willy Tarreau977b8e42006-12-29 14:19:17 +0100841 if (curproxy->cap & PR_CAP_RS) {
842 if (defproxy.capture_name)
843 curproxy->capture_name = strdup(defproxy.capture_name);
844 curproxy->capture_namelen = defproxy.capture_namelen;
845 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200847
Willy Tarreau977b8e42006-12-29 14:19:17 +0100848 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100849 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100850 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100851 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100852 curproxy->uri_auth = defproxy.uri_auth;
853 curproxy->mon_net = defproxy.mon_net;
854 curproxy->mon_mask = defproxy.mon_mask;
855 if (defproxy.monitor_uri)
856 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
857 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100858 if (defproxy.defbe.name)
859 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100860 }
861
862 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100863 curproxy->timeout.connect = defproxy.timeout.connect;
864 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100865 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100866 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100867 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100868 curproxy->source_addr = defproxy.source_addr;
869 }
870
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 curproxy->mode = defproxy.mode;
872 curproxy->logfac1 = defproxy.logfac1;
873 curproxy->logsrv1 = defproxy.logsrv1;
874 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200875 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 curproxy->logfac2 = defproxy.logfac2;
877 curproxy->logsrv2 = defproxy.logsrv2;
878 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200879 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100881 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
882 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200883
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 return 0;
885 }
886 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
887 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100888 /* FIXME-20070101: we should do this too at the end of the
889 * config parsing to free all default values.
890 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200891 free(defproxy.check_req);
892 free(defproxy.cookie_name);
893 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100894 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200895 free(defproxy.capture_name);
896 free(defproxy.monitor_uri);
897 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100898 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200899 free(defproxy.fwdfor_hdr_name);
900 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100901
Willy Tarreaua534fea2008-08-03 12:19:50 +0200902 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
903 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100904
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 /* we cannot free uri_auth because it might already be used */
906 init_default_instance();
907 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100908 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 return 0;
910 }
911 else if (curproxy == NULL) {
912 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
913 return -1;
914 }
915
Willy Tarreau977b8e42006-12-29 14:19:17 +0100916
917 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100919 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100920 int cur_arg;
921
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 if (curproxy == &defproxy) {
923 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
924 return -1;
925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
927 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928
929 if (strchr(args[1], ':') == NULL) {
930 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
931 file, linenum, args[0]);
932 return -1;
933 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100934
935 last_listen = curproxy->listen;
936 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 if (!curproxy->listen)
938 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100939
940 cur_arg = 2;
941 while (*(args[cur_arg])) {
942 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
943#ifdef SO_BINDTODEVICE
944 struct listener *l;
945
946 if (!*args[cur_arg + 1]) {
947 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
948 file, linenum, args[0]);
949 return -1;
950 }
951
952 for (l = curproxy->listen; l != last_listen; l = l->next)
953 l->interface = strdup(args[cur_arg + 1]);
954
955 global.last_checks |= LSTCHK_NETADM;
956
957 cur_arg += 2;
958 continue;
959#else
960 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
961 file, linenum, args[0], args[cur_arg]);
962 return -1;
963#endif
964 }
Willy Tarreaube1b9182009-06-14 18:48:19 +0200965 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
966#ifdef TCP_MAXSEG
967 struct listener *l;
968 int mss;
969
970 if (!*args[cur_arg + 1]) {
971 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
972 file, linenum, args[0]);
973 return -1;
974 }
975
976 mss = str2uic(args[cur_arg + 1]);
977 if (mss < 1 || mss > 65535) {
978 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
979 file, linenum, args[0]);
980 return -1;
981 }
982
983 for (l = curproxy->listen; l != last_listen; l = l->next)
984 l->maxseg = mss;
985
986 cur_arg += 2;
987 continue;
988#else
989 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
990 file, linenum, args[0], args[cur_arg]);
991 return -1;
992#endif
993 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100994 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100995#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100996 struct listener *l;
997
998 for (l = curproxy->listen; l != last_listen; l = l->next)
999 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001000
1001 cur_arg ++;
1002 continue;
1003#else
1004 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1005 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001006 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001007#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001008 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001009 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001010 file, linenum, args[0]);
1011 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001013 global.maxsock++;
1014 return 0;
1015 }
1016 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1017 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1018 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1019 file, linenum, args[0]);
1020 return -1;
1021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1023 return 0;
1024
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 /* flush useless bits */
1026 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
1027 return 0;
1028 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001029 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001030 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1031 return 0;
1032
Willy Tarreau1c47f852006-07-09 08:22:27 +02001033 if (!*args[1]) {
1034 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1035 file, linenum, args[0]);
1036 return -1;
1037 }
1038
Willy Tarreaua534fea2008-08-03 12:19:50 +02001039 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001040 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001041 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001042 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001043 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1044
1045 return 0;
1046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1048 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1049 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1050 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1051 else {
1052 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
1053 return -1;
1054 }
1055 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001056 else if (!strcmp(args[0], "id")) {
1057 struct proxy *target;
1058
1059 if (curproxy == &defproxy) {
1060 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1061 file, linenum, args[0]);
1062 return -1;
1063 }
1064
1065 if (!*args[1]) {
1066 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1067 file, linenum, args[0]);
1068 return -1;
1069 }
1070
1071 curproxy->uuid = atol(args[1]);
1072
1073 if (curproxy->uuid < 1001) {
1074 Alert("parsing [%s:%d]: custom id has to be > 1000",
1075 file, linenum);
1076 return -1;
1077 }
1078
1079 for (target = proxy; target; target = target->next)
1080 if (curproxy != target && curproxy->uuid == target->uuid) {
1081 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1082 file, linenum, curproxy->id, target->id);
1083 return -1;
1084 }
1085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1087 curproxy->state = PR_STSTOPPED;
1088 }
1089 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1090 curproxy->state = PR_STNEW;
1091 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001092 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1093 int cur_arg = 1;
1094 unsigned int set = 0;
1095
1096 while (*args[cur_arg]) {
1097 int u;
1098 if (strcmp(args[cur_arg], "all") == 0) {
1099 set = 0;
1100 break;
1101 }
1102 else if (strcmp(args[cur_arg], "odd") == 0) {
1103 set |= 0x55555555;
1104 }
1105 else if (strcmp(args[cur_arg], "even") == 0) {
1106 set |= 0xAAAAAAAA;
1107 }
1108 else {
1109 u = str2uic(args[cur_arg]);
1110 if (u < 1 || u > 32) {
1111 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1112 file, linenum, args[0]);
1113 return -1;
1114 }
1115 if (u > global.nbproc) {
1116 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1117 file, linenum, args[0]);
1118 }
1119 set |= 1 << (u - 1);
1120 }
1121 cur_arg++;
1122 }
1123 curproxy->bind_proc = set;
1124 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001125 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001126 if (curproxy == &defproxy) {
1127 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1128 return -1;
1129 }
1130
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001131 err = invalid_char(args[1]);
1132 if (err) {
1133 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1134 file, linenum, *err, args[1]);
1135 return -1;
1136 }
1137
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001138 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1139 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1140 file, linenum, args[1]);
1141 return -1;
1142 }
1143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1145 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1148 return 0;
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 if (*(args[1]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1152 file, linenum, args[0]);
1153 return -1;
1154 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001155
1156 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 curproxy->cookie_name = strdup(args[1]);
1158 curproxy->cookie_len = strlen(curproxy->cookie_name);
1159
1160 cur_arg = 2;
1161 while (*(args[cur_arg])) {
1162 if (!strcmp(args[cur_arg], "rewrite")) {
1163 curproxy->options |= PR_O_COOK_RW;
1164 }
1165 else if (!strcmp(args[cur_arg], "indirect")) {
1166 curproxy->options |= PR_O_COOK_IND;
1167 }
1168 else if (!strcmp(args[cur_arg], "insert")) {
1169 curproxy->options |= PR_O_COOK_INS;
1170 }
1171 else if (!strcmp(args[cur_arg], "nocache")) {
1172 curproxy->options |= PR_O_COOK_NOC;
1173 }
1174 else if (!strcmp(args[cur_arg], "postonly")) {
1175 curproxy->options |= PR_O_COOK_POST;
1176 }
1177 else if (!strcmp(args[cur_arg], "prefix")) {
1178 curproxy->options |= PR_O_COOK_PFX;
1179 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001180 else if (!strcmp(args[cur_arg], "domain")) {
1181 if (!*args[cur_arg + 1]) {
1182 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1183 file, linenum, args[cur_arg]);
1184 return -1;
1185 }
1186
1187 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1188 /* rfc2109, 4.3.2 Rejecting Cookies */
1189 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1190 " dots or does not start with a dot.\n",
1191 file, linenum, args[cur_arg + 1]);
1192 return -1;
1193 }
1194
1195 err = invalid_domainchar(args[cur_arg + 1]);
1196 if (err) {
1197 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1198 file, linenum, *err, args[cur_arg + 1]);
1199 return -1;
1200 }
1201
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001202 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001203 cur_arg++;
1204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001206 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 file, linenum, args[0]);
1208 return -1;
1209 }
1210 cur_arg++;
1211 }
1212 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1213 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1214 file, linenum);
1215 return -1;
1216 }
1217
1218 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1219 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1220 file, linenum);
1221 return -1;
1222 }
1223 }/* end else if (!strcmp(args[0], "cookie")) */
1224 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001225
Willy Tarreau977b8e42006-12-29 14:19:17 +01001226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1227 return 0;
1228
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 if (*(args[5]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1231 file, linenum, args[0]);
1232 return -1;
1233 }
1234 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001235 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 curproxy->appsession_name = strdup(args[1]);
1237 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1238 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001239 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1240 if (err) {
1241 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1242 file, linenum, *err, args[0]);
1243 return -1;
1244 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001245 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001246
Willy Tarreau51041c72007-09-09 21:56:53 +02001247 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 return -1;
1250 }
1251 } /* Url App Session */
1252 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001253 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1254 return 0;
1255
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 if (*(args[4]) == 0) {
1258 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1259 file, linenum, args[0]);
1260 return -1;
1261 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001262 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001263 curproxy->capture_name = strdup(args[2]);
1264 curproxy->capture_namelen = strlen(curproxy->capture_name);
1265 curproxy->capture_len = atol(args[4]);
1266 if (curproxy->capture_len >= CAPTURE_LEN) {
1267 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1268 file, linenum, CAPTURE_LEN - 1);
1269 curproxy->capture_len = CAPTURE_LEN - 1;
1270 }
1271 curproxy->to_log |= LW_COOKIE;
1272 }
1273 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1274 struct cap_hdr *hdr;
1275
1276 if (curproxy == &defproxy) {
1277 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1278 return -1;
1279 }
1280
1281 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1282 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1283 file, linenum, args[0], args[1]);
1284 return -1;
1285 }
1286
1287 hdr = calloc(sizeof(struct cap_hdr), 1);
1288 hdr->next = curproxy->req_cap;
1289 hdr->name = strdup(args[3]);
1290 hdr->namelen = strlen(args[3]);
1291 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001292 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293 hdr->index = curproxy->nb_req_cap++;
1294 curproxy->req_cap = hdr;
1295 curproxy->to_log |= LW_REQHDR;
1296 }
1297 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1298 struct cap_hdr *hdr;
1299
1300 if (curproxy == &defproxy) {
1301 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1302 return -1;
1303 }
1304
1305 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1306 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1307 file, linenum, args[0], args[1]);
1308 return -1;
1309 }
1310 hdr = calloc(sizeof(struct cap_hdr), 1);
1311 hdr->next = curproxy->rsp_cap;
1312 hdr->name = strdup(args[3]);
1313 hdr->namelen = strlen(args[3]);
1314 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001315 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 hdr->index = curproxy->nb_rsp_cap++;
1317 curproxy->rsp_cap = hdr;
1318 curproxy->to_log |= LW_RSPHDR;
1319 }
1320 else {
1321 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1322 file, linenum, args[0]);
1323 return -1;
1324 }
1325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1328 return 0;
1329
Willy Tarreaubaaee002006-06-26 02:48:02 +02001330 if (*(args[1]) == 0) {
1331 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1332 file, linenum, args[0]);
1333 return -1;
1334 }
1335 curproxy->conn_retries = atol(args[1]);
1336 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001337 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1338 int pol = ACL_COND_NONE;
1339 struct acl_cond *cond;
1340
Willy Tarreaub099aca2008-10-12 17:26:37 +02001341 if (curproxy == &defproxy) {
1342 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1343 return -1;
1344 }
1345
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001346 if (!strcmp(args[1], "if"))
1347 pol = ACL_COND_IF;
1348 else if (!strcmp(args[1], "unless"))
1349 pol = ACL_COND_UNLESS;
1350
1351 if (pol == ACL_COND_NONE) {
1352 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1353 file, linenum, args[0]);
1354 return -1;
1355 }
1356
1357 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1358 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1359 file, linenum);
1360 return -1;
1361 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001362 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001363 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001364 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001365 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001366 else if (!strcmp(args[0], "redirect")) {
1367 int pol = ACL_COND_NONE;
1368 struct acl_cond *cond;
1369 struct redirect_rule *rule;
1370 int cur_arg;
1371 int type = REDIRECT_TYPE_NONE;
1372 int code = 302;
1373 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001374 char *cookie = NULL;
1375 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001376 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001377
1378 cur_arg = 1;
1379 while (*(args[cur_arg])) {
1380 if (!strcmp(args[cur_arg], "location")) {
1381 if (!*args[cur_arg + 1]) {
1382 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1383 file, linenum, args[0], args[cur_arg]);
1384 return -1;
1385 }
1386
1387 type = REDIRECT_TYPE_LOCATION;
1388 cur_arg++;
1389 destination = args[cur_arg];
1390 }
1391 else if (!strcmp(args[cur_arg], "prefix")) {
1392 if (!*args[cur_arg + 1]) {
1393 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1394 file, linenum, args[0], args[cur_arg]);
1395 return -1;
1396 }
1397
1398 type = REDIRECT_TYPE_PREFIX;
1399 cur_arg++;
1400 destination = args[cur_arg];
1401 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001402 else if (!strcmp(args[cur_arg], "set-cookie")) {
1403 if (!*args[cur_arg + 1]) {
1404 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1405 file, linenum, args[0], args[cur_arg]);
1406 return -1;
1407 }
1408
1409 cur_arg++;
1410 cookie = args[cur_arg];
1411 cookie_set = 1;
1412 }
1413 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1414 if (!*args[cur_arg + 1]) {
1415 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1416 file, linenum, args[0], args[cur_arg]);
1417 return -1;
1418 }
1419
1420 cur_arg++;
1421 cookie = args[cur_arg];
1422 cookie_set = 0;
1423 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001424 else if (!strcmp(args[cur_arg],"code")) {
1425 if (!*args[cur_arg + 1]) {
1426 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1427 file, linenum, args[0]);
1428 return -1;
1429 }
1430 cur_arg++;
1431 code = atol(args[cur_arg]);
1432 if (code < 301 || code > 303) {
1433 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1434 file, linenum, args[0], code);
1435 return -1;
1436 }
1437 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001438 else if (!strcmp(args[cur_arg],"drop-query")) {
1439 flags |= REDIRECT_FLAG_DROP_QS;
1440 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001441 else if (!strcmp(args[cur_arg], "if")) {
1442 pol = ACL_COND_IF;
1443 cur_arg++;
1444 break;
1445 }
1446 else if (!strcmp(args[cur_arg], "unless")) {
1447 pol = ACL_COND_UNLESS;
1448 cur_arg++;
1449 break;
1450 }
1451 else {
1452 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1453 file, linenum, args[0], args[cur_arg]);
1454 return -1;
1455 }
1456 cur_arg++;
1457 }
1458
1459 if (type == REDIRECT_TYPE_NONE) {
1460 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1461 file, linenum, args[0]);
1462 return -1;
1463 }
1464
1465 if (pol == ACL_COND_NONE) {
1466 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1467 file, linenum, args[0]);
1468 return -1;
1469 }
1470
1471 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001472 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001473 file, linenum, args[0]);
1474 return -1;
1475 }
1476
Willy Tarreaua9802632008-07-25 19:13:19 +02001477 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001478 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1479 rule->cond = cond;
1480 rule->rdr_str = strdup(destination);
1481 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001482 if (cookie) {
1483 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1484 * a clear consists in appending "; Max-Age=0" at the end.
1485 */
1486 rule->cookie_len = strlen(cookie);
1487 if (cookie_set)
1488 rule->cookie_str = strdup(cookie);
1489 else {
1490 rule->cookie_str = malloc(rule->cookie_len + 12);
1491 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1492 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1493 rule->cookie_len += 11;
1494 }
1495 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001496 rule->type = type;
1497 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001498 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001499 LIST_INIT(&rule->list);
1500 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001501 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001502 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001503 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001504 int pol = ACL_COND_NONE;
1505 struct acl_cond *cond;
1506 struct switching_rule *rule;
1507
Willy Tarreaub099aca2008-10-12 17:26:37 +02001508 if (curproxy == &defproxy) {
1509 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1510 return -1;
1511 }
1512
Willy Tarreau55ea7572007-06-17 19:56:27 +02001513 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1514 return 0;
1515
1516 if (*(args[1]) == 0) {
1517 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1518 return -1;
1519 }
1520
1521 if (!strcmp(args[2], "if"))
1522 pol = ACL_COND_IF;
1523 else if (!strcmp(args[2], "unless"))
1524 pol = ACL_COND_UNLESS;
1525
1526 if (pol == ACL_COND_NONE) {
1527 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1528 file, linenum, args[0]);
1529 return -1;
1530 }
1531
1532 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001533 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001534 file, linenum);
1535 return -1;
1536 }
1537
Willy Tarreaua9802632008-07-25 19:13:19 +02001538 cond->line = linenum;
1539 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001540 struct acl *acl;
1541 const char *name;
1542
1543 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1544 name = acl ? acl->name : "(unknown)";
1545 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1546 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001547 }
1548
Willy Tarreau55ea7572007-06-17 19:56:27 +02001549 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1550 rule->cond = cond;
1551 rule->be.name = strdup(args[1]);
1552 LIST_INIT(&rule->list);
1553 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1557 return 0;
1558
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1560 curproxy->uri_auth = NULL; /* we must detach from the default config */
1561
1562 if (*(args[1]) == 0) {
1563 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1564 return -1;
1565 } else if (!strcmp(args[1], "uri")) {
1566 if (*(args[2]) == 0) {
1567 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1568 return -1;
1569 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1570 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1571 return -1;
1572 }
1573 } else if (!strcmp(args[1], "realm")) {
1574 if (*(args[2]) == 0) {
1575 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1576 return -1;
1577 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1578 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1579 return -1;
1580 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001581 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001582 unsigned interval;
1583
1584 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1585 if (err) {
1586 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1587 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001588 return -1;
1589 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1590 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1591 return -1;
1592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 } else if (!strcmp(args[1], "auth")) {
1594 if (*(args[2]) == 0) {
1595 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1596 return -1;
1597 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1598 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1599 return -1;
1600 }
1601 } else if (!strcmp(args[1], "scope")) {
1602 if (*(args[2]) == 0) {
1603 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1604 return -1;
1605 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1606 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1607 return -1;
1608 }
1609 } else if (!strcmp(args[1], "enable")) {
1610 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1611 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1612 return -1;
1613 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001614 } else if (!strcmp(args[1], "hide-version")) {
1615 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1616 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1617 return -1;
1618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001620 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 file, linenum, args[0]);
1622 return -1;
1623 }
1624 }
1625 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001626 int optnum;
1627
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001628 if (*(args[1]) == '\0') {
1629 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1630 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 return -1;
1632 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001633
1634 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1635 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1636 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1637 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001638
Willy Tarreau3842f002009-06-14 11:39:52 +02001639 curproxy->no_options &= ~cfg_opts[optnum].val;
1640 curproxy->options &= ~cfg_opts[optnum].val;
1641
1642 switch (kwm) {
1643 case KWM_STD:
1644 curproxy->options |= cfg_opts[optnum].val;
1645 break;
1646 case KWM_NO:
1647 curproxy->no_options |= cfg_opts[optnum].val;
1648 break;
1649 case KWM_DEF: /* already cleared */
1650 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001651 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001652
Willy Tarreau13943ab2006-12-31 00:24:10 +01001653 return 0;
1654 }
1655 }
1656
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001657 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1658 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1659 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1660 return 0;
1661
Willy Tarreau3842f002009-06-14 11:39:52 +02001662 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1663 curproxy->options2 &= ~cfg_opts2[optnum].val;
1664
1665 switch (kwm) {
1666 case KWM_STD:
1667 curproxy->options2 |= cfg_opts2[optnum].val;
1668 break;
1669 case KWM_NO:
1670 curproxy->no_options2 |= cfg_opts2[optnum].val;
1671 break;
1672 case KWM_DEF: /* already cleared */
1673 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001674 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001675 return 0;
1676 }
1677 }
1678
Willy Tarreau3842f002009-06-14 11:39:52 +02001679 if (kwm != KWM_STD) {
1680 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001681 file, linenum, args[1]);
1682 return -1;
1683 }
1684
Willy Tarreau13943ab2006-12-31 00:24:10 +01001685 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 /* generate a complete HTTP log */
1687 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1688 else if (!strcmp(args[1], "tcplog"))
1689 /* generate a detailed TCP log */
1690 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 else if (!strcmp(args[1], "tcpka")) {
1692 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001693 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1694 return 0;
1695
1696 if (curproxy->cap & PR_CAP_FE)
1697 curproxy->options |= PR_O_TCP_CLI_KA;
1698 if (curproxy->cap & PR_CAP_BE)
1699 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700 }
1701 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001702 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1703 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001705 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001706 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001707 curproxy->options &= ~PR_O_SMTP_CHK;
1708 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 if (!*args[2]) { /* no argument */
1710 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1711 curproxy->check_len = strlen(DEF_CHECK_REQ);
1712 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001713 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 curproxy->check_req = (char *)malloc(reqlen);
1715 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1716 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1717 } else { /* more arguments : METHOD URI [HTTP_VER] */
1718 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1719 if (*args[4])
1720 reqlen += strlen(args[4]);
1721 else
1722 reqlen += strlen("HTTP/1.0");
1723
1724 curproxy->check_req = (char *)malloc(reqlen);
1725 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1726 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1727 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001728 }
1729 else if (!strcmp(args[1], "ssl-hello-chk")) {
1730 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1732 return 0;
1733
Willy Tarreaua534fea2008-08-03 12:19:50 +02001734 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001735 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001736 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001737 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 }
Willy Tarreau23677902007-05-08 23:50:35 +02001739 else if (!strcmp(args[1], "smtpchk")) {
1740 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001741 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001742 curproxy->options &= ~PR_O_HTTP_CHK;
1743 curproxy->options &= ~PR_O_SSL3_CHK;
1744 curproxy->options |= PR_O_SMTP_CHK;
1745
1746 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1747 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1748 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1749 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1750 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1751 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1752 curproxy->check_req = (char *)malloc(reqlen);
1753 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1754 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1755 } else {
1756 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1757 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1758 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1759 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1760 }
1761 }
1762 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001763 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001764 int cur_arg;
1765
1766 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1767 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001768 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001769
1770 curproxy->options |= PR_O_FWDFOR;
1771
1772 free(curproxy->fwdfor_hdr_name);
1773 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1774 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1775
1776 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1777 cur_arg = 2;
1778 while (*(args[cur_arg])) {
1779 if (!strcmp(args[cur_arg], "except")) {
1780 /* suboption except - needs additional argument for it */
1781 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1782 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1783 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001784 return -1;
1785 }
1786 /* flush useless bits */
1787 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001788 cur_arg += 2;
1789 } else if (!strcmp(args[cur_arg], "header")) {
1790 /* suboption header - needs additional argument for it */
1791 if (*(args[cur_arg+1]) == 0) {
1792 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1793 file, linenum, args[0], args[1], args[cur_arg]);
1794 return -1;
1795 }
1796 free(curproxy->fwdfor_hdr_name);
1797 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1798 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1799 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001800 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001801 /* unknown suboption - catchall */
1802 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1803 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001804 return -1;
1805 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001806 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001807 }
Maik Broemme2850cb42009-04-17 18:53:21 +02001808 else if (!strcmp(args[1], "originalto")) {
1809 int cur_arg;
1810
1811 /* insert x-original-to field, but not for the IP address listed as an except.
1812 * set default options (ie: bitfield, header name, etc)
1813 */
1814
1815 curproxy->options |= PR_O_ORGTO;
1816
1817 free(curproxy->orgto_hdr_name);
1818 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
1819 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
1820
1821 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1822 cur_arg = 2;
1823 while (*(args[cur_arg])) {
1824 if (!strcmp(args[cur_arg], "except")) {
1825 /* suboption except - needs additional argument for it */
1826 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
1827 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1828 file, linenum, args[0], args[1], args[cur_arg]);
1829 return -1;
1830 }
1831 /* flush useless bits */
1832 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
1833 cur_arg += 2;
1834 } else if (!strcmp(args[cur_arg], "header")) {
1835 /* suboption header - needs additional argument for it */
1836 if (*(args[cur_arg+1]) == 0) {
1837 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1838 file, linenum, args[0], args[1], args[cur_arg]);
1839 return -1;
1840 }
1841 free(curproxy->orgto_hdr_name);
1842 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
1843 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
1844 cur_arg += 2;
1845 } else {
1846 /* unknown suboption - catchall */
1847 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1848 file, linenum, args[0], args[1]);
1849 return -1;
1850 }
1851 } /* end while loop */
1852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853 else {
1854 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1855 return -1;
1856 }
1857 return 0;
1858 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001859 else if (!strcmp(args[0], "default_backend")) {
1860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1861 return 0;
1862
1863 if (*(args[1]) == 0) {
1864 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1865 return -1;
1866 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001867 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001868 curproxy->defbe.name = strdup(args[1]);
1869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1872 return 0;
1873
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001874 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1875 file, linenum, args[0]);
1876
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 /* enable reconnections to dispatch */
1878 curproxy->options |= PR_O_REDISP;
1879 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001880 else if (!strcmp(args[0], "http-check")) {
1881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1882 return 0;
1883
1884 if (strcmp(args[1], "disable-on-404") == 0) {
1885 /* enable a graceful server shutdown on an HTTP 404 response */
1886 curproxy->options |= PR_O_DISABLE404;
1887 }
1888 else {
1889 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1890 return -1;
1891 }
1892 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001893 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001894 if (curproxy == &defproxy) {
1895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1896 return -1;
1897 }
1898
Willy Tarreaub80c2302007-11-30 20:51:32 +01001899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1900 return 0;
1901
1902 if (strcmp(args[1], "fail") == 0) {
1903 /* add a condition to fail monitor requests */
1904 int pol = ACL_COND_NONE;
1905 struct acl_cond *cond;
1906
1907 if (!strcmp(args[2], "if"))
1908 pol = ACL_COND_IF;
1909 else if (!strcmp(args[2], "unless"))
1910 pol = ACL_COND_UNLESS;
1911
1912 if (pol == ACL_COND_NONE) {
1913 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1914 file, linenum, args[0], args[1]);
1915 return -1;
1916 }
1917
1918 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1919 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1920 file, linenum, args[0], args[1]);
1921 return -1;
1922 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001923 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001924 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1925 }
1926 else {
1927 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1928 return -1;
1929 }
1930 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931#ifdef TPROXY
1932 else if (!strcmp(args[0], "transparent")) {
1933 /* enable transparent proxy connections */
1934 curproxy->options |= PR_O_TRANSP;
1935 }
1936#endif
1937 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001938 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1939 return 0;
1940
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 if (*(args[1]) == 0) {
1942 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1943 return -1;
1944 }
1945 curproxy->maxconn = atol(args[1]);
1946 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001947 else if (!strcmp(args[0], "backlog")) { /* backlog */
1948 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1949 return 0;
1950
1951 if (*(args[1]) == 0) {
1952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1953 return -1;
1954 }
1955 curproxy->backlog = atol(args[1]);
1956 }
Willy Tarreau86034312006-12-29 00:10:33 +01001957 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1959 return 0;
1960
Willy Tarreau86034312006-12-29 00:10:33 +01001961 if (*(args[1]) == 0) {
1962 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1963 return -1;
1964 }
1965 curproxy->fullconn = atol(args[1]);
1966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1968 if (*(args[1]) == 0) {
1969 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1970 return -1;
1971 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001972 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1973 if (err) {
1974 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1975 file, linenum, *err);
1976 return -1;
1977 }
1978 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979 }
1980 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1981 if (curproxy == &defproxy) {
1982 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1983 return -1;
1984 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001985 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1986 return 0;
1987
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 if (strchr(args[1], ':') == NULL) {
1989 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1990 return -1;
1991 }
1992 curproxy->dispatch_addr = *str2sa(args[1]);
1993 }
1994 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1996 return 0;
1997
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001998 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001999 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2000 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2001 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 }
2004 else if (!strcmp(args[0], "server")) { /* server address */
2005 int cur_arg;
2006 char *rport;
2007 char *raddr;
2008 short realport;
2009 int do_check;
2010
2011 if (curproxy == &defproxy) {
2012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2013 return -1;
2014 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002015 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2016 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017
2018 if (!*args[2]) {
2019 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2020 file, linenum, args[0]);
2021 return -1;
2022 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002023
2024 err = invalid_char(args[1]);
2025 if (err) {
2026 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2027 file, linenum, *err, args[1]);
2028 return -1;
2029 }
2030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2032 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2033 return -1;
2034 }
2035
2036 /* the servers are linked backwards first */
2037 newsrv->next = curproxy->srv;
2038 curproxy->srv = newsrv;
2039 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002040 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041
2042 LIST_INIT(&newsrv->pendconns);
2043 do_check = 0;
2044 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002045 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 newsrv->id = strdup(args[1]);
2047
2048 /* several ways to check the port component :
2049 * - IP => port=+0, relative
2050 * - IP: => port=+0, relative
2051 * - IP:N => port=N, absolute
2052 * - IP:+N => port=+N, relative
2053 * - IP:-N => port=-N, relative
2054 */
2055 raddr = strdup(args[2]);
2056 rport = strchr(raddr, ':');
2057 if (rport) {
2058 *rport++ = 0;
2059 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002060 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 newsrv->state |= SRV_MAPPORTS;
2062 } else {
2063 realport = 0;
2064 newsrv->state |= SRV_MAPPORTS;
2065 }
2066
2067 newsrv->addr = *str2sa(raddr);
2068 newsrv->addr.sin_port = htons(realport);
2069 free(raddr);
2070
2071 newsrv->curfd = -1; /* no health-check in progress */
2072 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002073 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2074 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 newsrv->rise = DEF_RISETIME;
2076 newsrv->fall = DEF_FALLTIME;
2077 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002078 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002079 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002080 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002081
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 cur_arg = 3;
2083 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002084 if (!strcmp(args[cur_arg], "id")) {
2085 struct server *target;
2086
2087 if (!*args[cur_arg + 1]) {
2088 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2089 file, linenum, args[cur_arg]);
2090 return -1;
2091 }
2092
2093 newsrv->puid = atol(args[cur_arg + 1]);
2094
2095 if (newsrv->puid< 1001) {
2096 Alert("parsing [%s:%d]: custom id has to be > 1000",
2097 file, linenum);
2098 return -1;
2099 }
2100
2101 for (target = proxy->srv; target; target = target->next)
2102 if (newsrv != target && newsrv->puid == target->puid) {
2103 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2104 file, linenum, newsrv->id, target->id);
2105 return -1;
2106 }
2107 cur_arg += 2;
2108 }
2109 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 newsrv->cookie = strdup(args[cur_arg + 1]);
2111 newsrv->cklen = strlen(args[cur_arg + 1]);
2112 cur_arg += 2;
2113 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002114 else if (!strcmp(args[cur_arg], "redir")) {
2115 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2116 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2117 cur_arg += 2;
2118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 else if (!strcmp(args[cur_arg], "rise")) {
2120 newsrv->rise = atol(args[cur_arg + 1]);
2121 newsrv->health = newsrv->rise;
2122 cur_arg += 2;
2123 }
2124 else if (!strcmp(args[cur_arg], "fall")) {
2125 newsrv->fall = atol(args[cur_arg + 1]);
2126 cur_arg += 2;
2127 }
2128 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002129 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2130 if (err) {
2131 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2132 file, linenum, *err, newsrv->id);
2133 return -1;
2134 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002135 if (val <= 0) {
2136 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2137 file, linenum, val, args[cur_arg], newsrv->id);
2138 return -1;
2139 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002140 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 cur_arg += 2;
2142 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002143 else if (!strcmp(args[cur_arg], "fastinter")) {
2144 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2145 if (err) {
2146 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2147 file, linenum, *err, newsrv->id);
2148 return -1;
2149 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002150 if (val <= 0) {
2151 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2152 file, linenum, val, args[cur_arg], newsrv->id);
2153 return -1;
2154 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002155 newsrv->fastinter = val;
2156 cur_arg += 2;
2157 }
2158 else if (!strcmp(args[cur_arg], "downinter")) {
2159 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2160 if (err) {
2161 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2162 file, linenum, *err, newsrv->id);
2163 return -1;
2164 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002165 if (val <= 0) {
2166 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2167 file, linenum, val, args[cur_arg], newsrv->id);
2168 return -1;
2169 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002170 newsrv->downinter = val;
2171 cur_arg += 2;
2172 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002173 else if (!strcmp(args[cur_arg], "addr")) {
2174 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002175 cur_arg += 2;
2176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 else if (!strcmp(args[cur_arg], "port")) {
2178 newsrv->check_port = atol(args[cur_arg + 1]);
2179 cur_arg += 2;
2180 }
2181 else if (!strcmp(args[cur_arg], "backup")) {
2182 newsrv->state |= SRV_BACKUP;
2183 cur_arg ++;
2184 }
2185 else if (!strcmp(args[cur_arg], "weight")) {
2186 int w;
2187 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002188 if (w < 0 || w > 256) {
2189 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 file, linenum, newsrv->id, w);
2191 return -1;
2192 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002193 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 cur_arg += 2;
2195 }
2196 else if (!strcmp(args[cur_arg], "minconn")) {
2197 newsrv->minconn = atol(args[cur_arg + 1]);
2198 cur_arg += 2;
2199 }
2200 else if (!strcmp(args[cur_arg], "maxconn")) {
2201 newsrv->maxconn = atol(args[cur_arg + 1]);
2202 cur_arg += 2;
2203 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002204 else if (!strcmp(args[cur_arg], "maxqueue")) {
2205 newsrv->maxqueue = atol(args[cur_arg + 1]);
2206 cur_arg += 2;
2207 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002208 else if (!strcmp(args[cur_arg], "slowstart")) {
2209 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002210 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002211 if (err) {
2212 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2213 file, linenum, *err, newsrv->id);
2214 return -1;
2215 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002216 if (val <= 0) {
2217 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2218 file, linenum, val, args[cur_arg], newsrv->id);
2219 return -1;
2220 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002221 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002222 cur_arg += 2;
2223 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002224 else if (!strcmp(args[cur_arg], "track")) {
2225
2226 if (!*args[cur_arg + 1]) {
2227 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2228 file, linenum);
2229 return -1;
2230 }
2231
2232 newsrv->trackit = strdup(args[cur_arg + 1]);
2233
2234 cur_arg += 2;
2235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 else if (!strcmp(args[cur_arg], "check")) {
2237 global.maxsock++;
2238 do_check = 1;
2239 cur_arg += 1;
2240 }
2241 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002242 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002244#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002245 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002246 file, linenum, "source", "usesrc");
2247#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002248 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002250#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 return -1;
2252 }
2253 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002254 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2255
2256 if (port_low != port_high) {
2257 int i;
2258 if (port_low <= 0 || port_low > 65535 ||
2259 port_high <= 0 || port_high > 65535 ||
2260 port_low > port_high) {
2261 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2262 file, linenum, port_low, port_high);
2263 return -1;
2264 }
2265 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2266 for (i = 0; i < newsrv->sport_range->size; i++)
2267 newsrv->sport_range->ports[i] = port_low + i;
2268 }
2269
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002271 while (*(args[cur_arg])) {
2272 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002273#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2274#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002275 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2276 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2277 file, linenum, "usesrc", "source");
2278 return -1;
2279 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002280#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002281 if (!*args[cur_arg + 1]) {
2282 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2283 file, linenum, "usesrc");
2284 return -1;
2285 }
2286 if (!strcmp(args[cur_arg + 1], "client")) {
2287 newsrv->state |= SRV_TPROXY_CLI;
2288 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2289 newsrv->state |= SRV_TPROXY_CIP;
2290 } else {
2291 newsrv->state |= SRV_TPROXY_ADDR;
2292 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2293 }
2294 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002295#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002296 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002297#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002298 cur_arg += 2;
2299 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002300#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002301 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002302 file, linenum, "usesrc");
2303 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002304#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2305 } /* "usesrc" */
2306
2307 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2308#ifdef SO_BINDTODEVICE
2309 if (!*args[cur_arg + 1]) {
2310 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2311 file, linenum, args[0]);
2312 return -1;
2313 }
2314 if (newsrv->iface_name)
2315 free(newsrv->iface_name);
2316
2317 newsrv->iface_name = strdup(args[cur_arg + 1]);
2318 newsrv->iface_len = strlen(newsrv->iface_name);
2319 global.last_checks |= LSTCHK_NETADM;
2320#else
2321 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2322 file, linenum, args[0], args[cur_arg]);
2323 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002324#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002325 cur_arg += 2;
2326 continue;
2327 }
2328 /* this keyword in not an option of "source" */
2329 break;
2330 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002332 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2333 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2334 file, linenum, "usesrc", "source");
2335 return -1;
2336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002338 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 +02002339 file, linenum, newsrv->id);
2340 return -1;
2341 }
2342 }
2343
2344 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002345 if (newsrv->trackit) {
2346 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2347 file, linenum);
2348 return -1;
2349 }
2350
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002351 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2352 newsrv->check_port = newsrv->check_addr.sin_port;
2353
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2355 newsrv->check_port = realport; /* by default */
2356 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002357 /* not yet valid, because no port was set on
2358 * the server either. We'll check if we have
2359 * a known port on the first listener.
2360 */
2361 struct listener *l;
2362 l = curproxy->listen;
2363 if (l) {
2364 int port;
2365 port = (l->addr.ss_family == AF_INET6)
2366 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2367 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2368 newsrv->check_port = port;
2369 }
2370 }
2371 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2373 file, linenum, newsrv->id);
2374 return -1;
2375 }
2376 newsrv->state |= SRV_CHECKED;
2377 }
2378
2379 if (newsrv->state & SRV_BACKUP)
2380 curproxy->srv_bck++;
2381 else
2382 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002383
2384 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 }
2386 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002387 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 int facility;
2389
2390 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2391 curproxy->logfac1 = global.logfac1;
2392 curproxy->logsrv1 = global.logsrv1;
2393 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002394 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 curproxy->logfac2 = global.logfac2;
2396 curproxy->logsrv2 = global.logsrv2;
2397 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002398 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002401 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402
2403 facility = get_log_facility(args[2]);
2404 if (facility < 0) {
2405 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2406 exit(1);
2407 }
2408
2409 level = 7; /* max syslog level = debug */
2410 if (*(args[3])) {
2411 level = get_log_level(args[3]);
2412 if (level < 0) {
2413 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2414 exit(1);
2415 }
2416 }
2417
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002418 minlvl = 0; /* limit syslog level to this level (emerg) */
2419 if (*(args[4])) {
2420 minlvl = get_log_level(args[4]);
2421 if (level < 0) {
2422 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2423 exit(1);
2424 }
2425 }
2426
Robert Tsai81ae1952007-12-05 10:47:29 +01002427 if (args[1][0] == '/') {
2428 logsrv.u.addr.sa_family = AF_UNIX;
2429 logsrv.u.un = *str2sun(args[1]);
2430 } else {
2431 logsrv.u.addr.sa_family = AF_INET;
2432 logsrv.u.in = *str2sa(args[1]);
2433 if (!logsrv.u.in.sin_port) {
2434 logsrv.u.in.sin_port =
2435 htons(SYSLOG_PORT);
2436 }
2437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438
2439 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002440 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 curproxy->logfac1 = facility;
2442 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002443 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
2445 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002446 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 curproxy->logfac2 = facility;
2448 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002449 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
2451 else {
2452 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2453 return -1;
2454 }
2455 }
2456 else {
2457 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2458 file, linenum);
2459 return -1;
2460 }
2461 }
2462 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002463 int cur_arg;
2464
Willy Tarreau977b8e42006-12-29 14:19:17 +01002465 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2466 return 0;
2467
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002469 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2470 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 return -1;
2472 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002473
2474 /* we must first clear any optional default setting */
2475 curproxy->options &= ~PR_O_TPXY_MASK;
2476 free(curproxy->iface_name);
2477 curproxy->iface_name = NULL;
2478 curproxy->iface_len = 0;
2479
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 curproxy->source_addr = *str2sa(args[1]);
2481 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002482
2483 cur_arg = 2;
2484 while (*(args[cur_arg])) {
2485 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002486#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2487#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002488 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2489 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2490 file, linenum, "usesrc");
2491 return -1;
2492 }
2493#endif
2494 if (!*args[cur_arg + 1]) {
2495 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2496 file, linenum, "usesrc");
2497 return -1;
2498 }
2499
2500 if (!strcmp(args[cur_arg + 1], "client")) {
2501 curproxy->options |= PR_O_TPXY_CLI;
2502 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2503 curproxy->options |= PR_O_TPXY_CIP;
2504 } else {
2505 curproxy->options |= PR_O_TPXY_ADDR;
2506 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2507 }
2508 global.last_checks |= LSTCHK_NETADM;
2509#if !defined(CONFIG_HAP_LINUX_TPROXY)
2510 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002511#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002512#else /* no TPROXY support */
2513 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002514 file, linenum, "usesrc");
2515 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002516#endif
2517 cur_arg += 2;
2518 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002519 }
2520
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002521 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2522#ifdef SO_BINDTODEVICE
2523 if (!*args[cur_arg + 1]) {
2524 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2525 file, linenum, args[0]);
2526 return -1;
2527 }
2528 if (curproxy->iface_name)
2529 free(curproxy->iface_name);
2530
2531 curproxy->iface_name = strdup(args[cur_arg + 1]);
2532 curproxy->iface_len = strlen(curproxy->iface_name);
2533 global.last_checks |= LSTCHK_NETADM;
2534#else
2535 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2536 file, linenum, args[0], args[cur_arg]);
2537 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002538#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002539 cur_arg += 2;
2540 continue;
2541 }
2542 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2543 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002544 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002547 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2548 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2549 file, linenum, "usesrc", "source");
2550 return -1;
2551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2553 regex_t *preg;
2554 if (curproxy == &defproxy) {
2555 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2556 return -1;
2557 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002558 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2559 return 0;
2560
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 if (*(args[1]) == 0 || *(args[2]) == 0) {
2562 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2563 file, linenum, args[0]);
2564 return -1;
2565 }
2566
2567 preg = calloc(1, sizeof(regex_t));
2568 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2569 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2570 return -1;
2571 }
2572
2573 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2574 if (err) {
2575 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2576 file, linenum, *err);
2577 return -1;
2578 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002579 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2582 regex_t *preg;
2583 if (curproxy == &defproxy) {
2584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2585 return -1;
2586 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002587 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2588 return 0;
2589
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 if (*(args[1]) == 0) {
2591 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2592 return -1;
2593 }
2594
2595 preg = calloc(1, sizeof(regex_t));
2596 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2597 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2598 return -1;
2599 }
2600
2601 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002602 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 }
2604 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2605 regex_t *preg;
2606 if (curproxy == &defproxy) {
2607 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2608 return -1;
2609 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002610 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2611 return 0;
2612
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 if (*(args[1]) == 0) {
2614 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2615 return -1;
2616 }
2617
2618 preg = calloc(1, sizeof(regex_t));
2619 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2620 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2621 return -1;
2622 }
2623
2624 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002625 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
2627 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2628 regex_t *preg;
2629 if (curproxy == &defproxy) {
2630 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2631 return -1;
2632 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2634 return 0;
2635
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 if (*(args[1]) == 0) {
2637 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2638 return -1;
2639 }
2640
2641 preg = calloc(1, sizeof(regex_t));
2642 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2643 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2644 return -1;
2645 }
2646
2647 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002648 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
2650 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2651 regex_t *preg;
2652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2654 return -1;
2655 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002656 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2657 return 0;
2658
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 if (*(args[1]) == 0) {
2660 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2661 return -1;
2662 }
2663
2664 preg = calloc(1, sizeof(regex_t));
2665 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2666 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2667 return -1;
2668 }
2669
2670 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002671 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002673 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2674 regex_t *preg;
2675 if (curproxy == &defproxy) {
2676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2677 return -1;
2678 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2680 return 0;
2681
Willy Tarreaub8750a82006-09-03 09:56:00 +02002682 if (*(args[1]) == 0) {
2683 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2684 return -1;
2685 }
2686
2687 preg = calloc(1, sizeof(regex_t));
2688 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2689 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2690 return -1;
2691 }
2692
2693 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002694 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002695 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002696 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2697 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2700 return -1;
2701 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002702 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2703 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002704
Willy Tarreau977b8e42006-12-29 14:19:17 +01002705 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002706 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2707 file, linenum, args[0]);
2708 return -1;
2709 }
2710
2711 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002713 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2714 }
2715
2716 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002717 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002718 }
2719 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2720 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2723 return -1;
2724 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002725 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2726 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002727
Willy Tarreau977b8e42006-12-29 14:19:17 +01002728 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002729 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2730 file, linenum, args[0]);
2731 return -1;
2732 }
2733
2734 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002736 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2737 }
2738
2739 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002740 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2743 regex_t *preg;
2744 if (curproxy == &defproxy) {
2745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2746 return -1;
2747 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002748 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2749 return 0;
2750
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 if (*(args[1]) == 0 || *(args[2]) == 0) {
2752 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2753 file, linenum, args[0]);
2754 return -1;
2755 }
2756
2757 preg = calloc(1, sizeof(regex_t));
2758 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2759 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2760 return -1;
2761 }
2762
2763 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2764 if (err) {
2765 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2766 file, linenum, *err);
2767 return -1;
2768 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002769 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2772 regex_t *preg;
2773 if (curproxy == &defproxy) {
2774 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2775 return -1;
2776 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002777 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2778 return 0;
2779
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 if (*(args[1]) == 0) {
2781 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2782 return -1;
2783 }
2784
2785 preg = calloc(1, sizeof(regex_t));
2786 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2787 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2788 return -1;
2789 }
2790
2791 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002792 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 }
2794 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2795 regex_t *preg;
2796 if (curproxy == &defproxy) {
2797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2798 return -1;
2799 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002800 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2801 return 0;
2802
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 if (*(args[1]) == 0) {
2804 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2805 return -1;
2806 }
2807
2808 preg = calloc(1, sizeof(regex_t));
2809 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2810 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2811 return -1;
2812 }
2813
2814 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002815 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002816 }
2817 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2818 regex_t *preg;
2819 if (curproxy == &defproxy) {
2820 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2821 return -1;
2822 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002823 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2824 return 0;
2825
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826 if (*(args[1]) == 0) {
2827 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2828 return -1;
2829 }
2830
2831 preg = calloc(1, sizeof(regex_t));
2832 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2833 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2834 return -1;
2835 }
2836
2837 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002838 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
2840 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2841 regex_t *preg;
2842 if (curproxy == &defproxy) {
2843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2844 return -1;
2845 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002846 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2847 return 0;
2848
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 if (*(args[1]) == 0) {
2850 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2851 return -1;
2852 }
2853
2854 preg = calloc(1, sizeof(regex_t));
2855 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2856 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2857 return -1;
2858 }
2859
2860 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002861 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002862 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002863 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2864 regex_t *preg;
2865 if (curproxy == &defproxy) {
2866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2867 return -1;
2868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002869 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2870 return 0;
2871
Willy Tarreaub8750a82006-09-03 09:56:00 +02002872 if (*(args[1]) == 0) {
2873 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2874 return -1;
2875 }
2876
2877 preg = calloc(1, sizeof(regex_t));
2878 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2879 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2880 return -1;
2881 }
2882
2883 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002884 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2887 if (curproxy == &defproxy) {
2888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2889 return -1;
2890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2892 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893
2894 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2895 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2896 return 0;
2897 }
2898
2899 if (*(args[1]) == 0) {
2900 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2901 return -1;
2902 }
2903
2904 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002905 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 }
2907 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2908 regex_t *preg;
2909
2910 if (*(args[1]) == 0 || *(args[2]) == 0) {
2911 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2912 file, linenum, args[0]);
2913 return -1;
2914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002915 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2916 return 0;
2917
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 preg = calloc(1, sizeof(regex_t));
2919 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2920 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2921 return -1;
2922 }
2923
2924 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2925 if (err) {
2926 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2927 file, linenum, *err);
2928 return -1;
2929 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002930 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 }
2932 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2933 regex_t *preg;
2934 if (curproxy == &defproxy) {
2935 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2936 return -1;
2937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002938 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2939 return 0;
2940
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 if (*(args[1]) == 0) {
2942 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2943 return -1;
2944 }
2945
2946 preg = calloc(1, sizeof(regex_t));
2947 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2948 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2949 return -1;
2950 }
2951
2952 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2953 if (err) {
2954 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2955 file, linenum, *err);
2956 return -1;
2957 }
2958 }
2959 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2960 regex_t *preg;
2961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2963 return -1;
2964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2966 return 0;
2967
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968 if (*(args[1]) == 0) {
2969 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2970 return -1;
2971 }
2972
2973 preg = calloc(1, sizeof(regex_t));
2974 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2975 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2976 return -1;
2977 }
2978
2979 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2980 if (err) {
2981 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2982 file, linenum, *err);
2983 return -1;
2984 }
2985 }
2986 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2987 regex_t *preg;
2988 if (curproxy == &defproxy) {
2989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2990 return -1;
2991 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2993 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994
2995 if (*(args[1]) == 0 || *(args[2]) == 0) {
2996 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2997 file, linenum, args[0]);
2998 return -1;
2999 }
3000
3001 preg = calloc(1, sizeof(regex_t));
3002 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3003 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3004 return -1;
3005 }
3006
3007 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3008 if (err) {
3009 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3010 file, linenum, *err);
3011 return -1;
3012 }
3013 }
3014 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3015 regex_t *preg;
3016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3018 return -1;
3019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003020 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3021 return 0;
3022
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 if (*(args[1]) == 0) {
3024 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
3025 return -1;
3026 }
3027
3028 preg = calloc(1, sizeof(regex_t));
3029 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3030 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3031 return -1;
3032 }
3033
3034 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3035 if (err) {
3036 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3037 file, linenum, *err);
3038 return -1;
3039 }
3040 }
3041 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3042 regex_t *preg;
3043 if (curproxy == &defproxy) {
3044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3045 return -1;
3046 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3048 return 0;
3049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (*(args[1]) == 0) {
3051 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
3052 return -1;
3053 }
3054
3055 preg = calloc(1, sizeof(regex_t));
3056 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3057 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3058 return -1;
3059 }
3060
3061 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3062 if (err) {
3063 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3064 file, linenum, *err);
3065 return -1;
3066 }
3067 }
3068 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3069 if (curproxy == &defproxy) {
3070 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3071 return -1;
3072 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003073 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3074 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075
3076 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3077 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
3078 return 0;
3079 }
3080
3081 if (*(args[1]) == 0) {
3082 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
3083 return -1;
3084 }
3085
3086 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3087 }
3088 else if (!strcmp(args[0], "errorloc") ||
3089 !strcmp(args[0], "errorloc302") ||
3090 !strcmp(args[0], "errorloc303")) { /* error location */
3091 int errnum, errlen;
3092 char *err;
3093
Willy Tarreau977b8e42006-12-29 14:19:17 +01003094 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3095 return 0;
3096
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003098 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 return -1;
3100 }
3101
3102 errnum = atol(args[1]);
3103 if (!strcmp(args[0], "errorloc303")) {
3104 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3105 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3106 } else {
3107 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3108 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3109 }
3110
Willy Tarreau0f772532006-12-23 20:51:41 +01003111 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3112 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003113 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003114 curproxy->errmsg[rc].str = err;
3115 curproxy->errmsg[rc].len = errlen;
3116 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003119
3120 if (rc >= HTTP_ERR_SIZE) {
3121 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3122 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 free(err);
3124 }
3125 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003126 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3127 int errnum, errlen, fd;
3128 char *err;
3129 struct stat stat;
3130
3131 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3132 return 0;
3133
3134 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003135 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003136 return -1;
3137 }
3138
3139 fd = open(args[2], O_RDONLY);
3140 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3141 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3142 file, linenum, args[2], args[1]);
3143 if (fd >= 0)
3144 close(fd);
3145 return -1;
3146 }
3147
3148 if (stat.st_size <= BUFSIZE) {
3149 errlen = stat.st_size;
3150 } else {
3151 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3152 file, linenum, args[2], BUFSIZE);
3153 errlen = BUFSIZE;
3154 }
3155
3156 err = malloc(errlen); /* malloc() must succeed during parsing */
3157 errnum = read(fd, err, errlen);
3158 if (errnum != errlen) {
3159 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3160 file, linenum, args[2], args[1]);
3161 close(fd);
3162 free(err);
3163 return -1;
3164 }
3165 close(fd);
3166
3167 errnum = atol(args[1]);
3168 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3169 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003170 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003171 curproxy->errmsg[rc].str = err;
3172 curproxy->errmsg[rc].len = errlen;
3173 break;
3174 }
3175 }
3176
3177 if (rc >= HTTP_ERR_SIZE) {
3178 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3179 file, linenum, errnum);
3180 free(err);
3181 }
3182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003184 struct cfg_kw_list *kwl;
3185 int index;
3186
3187 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3188 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3189 if (kwl->kw[index].section != CFG_LISTEN)
3190 continue;
3191 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3192 /* prepare error message just in case */
3193 snprintf(trash, sizeof(trash),
3194 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003195 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3196 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003197 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3198 return -1;
3199 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003200 else if (rc > 0) {
3201 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3202 return 0;
3203 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003204 return 0;
3205 }
3206 }
3207 }
3208
Willy Tarreau6daf3432008-01-22 16:44:08 +01003209 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 return -1;
3211 }
3212 return 0;
3213}
3214
3215
3216/*
3217 * This function reads and parses the configuration file given in the argument.
3218 * returns 0 if OK, -1 if error.
3219 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003220int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003222 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 FILE *f;
3224 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 int confsect = CFG_NONE;
3226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 if ((f=fopen(file,"r")) == NULL)
3228 return -1;
3229
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003230 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003232 char *end;
3233 char *args[MAX_LINE_ARGS + 1];
3234 char *line = thisline;
3235
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 linenum++;
3237
3238 end = line + strlen(line);
3239
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003240 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3241 /* Check if we reached the limit and the last char is not \n.
3242 * Watch out for the last line without the terminating '\n'!
3243 */
3244 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003245 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003246 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003247 }
3248
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003250 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 line++;
3252
3253 arg = 0;
3254 args[arg] = line;
3255
3256 while (*line && arg < MAX_LINE_ARGS) {
3257 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3258 * C equivalent value. Other combinations left unchanged (eg: \1).
3259 */
3260 if (*line == '\\') {
3261 int skip = 0;
3262 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3263 *line = line[1];
3264 skip = 1;
3265 }
3266 else if (line[1] == 'r') {
3267 *line = '\r';
3268 skip = 1;
3269 }
3270 else if (line[1] == 'n') {
3271 *line = '\n';
3272 skip = 1;
3273 }
3274 else if (line[1] == 't') {
3275 *line = '\t';
3276 skip = 1;
3277 }
3278 else if (line[1] == 'x') {
3279 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3280 unsigned char hex1, hex2;
3281 hex1 = toupper(line[2]) - '0';
3282 hex2 = toupper(line[3]) - '0';
3283 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3284 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3285 *line = (hex1<<4) + hex2;
3286 skip = 3;
3287 }
3288 else {
3289 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003290 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
3292 }
3293 if (skip) {
3294 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3295 end -= skip;
3296 }
3297 line++;
3298 }
3299 else if (*line == '#' || *line == '\n' || *line == '\r') {
3300 /* end of string, end of loop */
3301 *line = 0;
3302 break;
3303 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003304 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003306 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003307 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 line++;
3309 args[++arg] = line;
3310 }
3311 else {
3312 line++;
3313 }
3314 }
3315
3316 /* empty line */
3317 if (!**args)
3318 continue;
3319
Willy Tarreau540abe42007-05-02 20:50:16 +02003320 /* zero out remaining args and ensure that at least one entry
3321 * is zeroed out.
3322 */
3323 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 args[arg] = line;
3325 }
3326
Willy Tarreau3842f002009-06-14 11:39:52 +02003327 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003328 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003329 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330 for (arg=0; *args[arg+1]; arg++)
3331 args[arg] = args[arg+1]; // shift args after inversion
3332 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003333 else if (!strcmp(args[0], "default")) {
3334 kwm = KWM_DEF;
3335 for (arg=0; *args[arg+1]; arg++)
3336 args[arg] = args[arg+1]; // shift args after inversion
3337 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003338
Willy Tarreau3842f002009-06-14 11:39:52 +02003339 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3340 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003341 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003342 }
3343
Willy Tarreau977b8e42006-12-29 14:19:17 +01003344 if (!strcmp(args[0], "listen") ||
3345 !strcmp(args[0], "frontend") ||
3346 !strcmp(args[0], "backend") ||
3347 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003348 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003350 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003351 cursection = strdup(args[0]);
3352 }
3353 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003355 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003356 cursection = strdup(args[0]);
3357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 /* else it's a section keyword */
3359
3360 switch (confsect) {
3361 case CFG_LISTEN:
Willy Tarreau3842f002009-06-14 11:39:52 +02003362 if (cfg_parse_listen(file, linenum, args, kwm) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003363 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 break;
3365 case CFG_GLOBAL:
Willy Tarreau3842f002009-06-14 11:39:52 +02003366 if (cfg_parse_global(file, linenum, args, kwm) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003367 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 break;
3369 default:
3370 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003371 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003374 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003375 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 fclose(f);
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003377 return 0;
3378 err:
3379 free(cursection);
3380 cursection = NULL;
3381 return -1;
3382}
3383
3384int check_config_validity()
3385{
3386 int cfgerr = 0;
3387 struct proxy *curproxy = NULL;
3388 struct server *newsrv = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389
3390 /*
3391 * Now, check for the integrity of all that we have collected.
3392 */
3393
3394 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003395 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003397 /* first, we will invert the proxy list order */
3398 curproxy = NULL;
3399 while (proxy) {
3400 struct proxy *next;
3401
3402 next = proxy->next;
3403 proxy->next = curproxy;
3404 curproxy = proxy;
3405 if (!next)
3406 break;
3407 proxy = next;
3408 }
3409
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003411 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003412 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
3414
3415 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003416 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003417 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003418
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003420 /* ensure we don't keep listeners uselessly bound */
3421 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 curproxy = curproxy->next;
3423 continue;
3424 }
3425
Willy Tarreauff01a212009-03-15 13:46:16 +01003426 switch (curproxy->mode) {
3427 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003428 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003429 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003430 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3431 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003432 cfgerr++;
3433 }
3434
3435 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003436 Warning("config : servers will be ignored for %s '%s'.\n",
3437 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003438 break;
3439
3440 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003441 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003442 break;
3443
3444 case PR_MODE_HTTP:
3445 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003446 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3447 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003448 cfgerr++;
3449 }
3450 break;
3451 }
3452
3453 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003454 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3455 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 cfgerr++;
3457 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003458
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003459 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3460 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3461 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003462 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
3463 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003464 cfgerr++;
3465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003467 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003468 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3469 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003470 cfgerr++;
3471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003473 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003474 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3475 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003476 }
3477 }
3478 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3479 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3480 /* If no LB algo is set in a backend, and we're not in
3481 * transparent mode, dispatch mode nor proxy mode, we
3482 * want to use balance roundrobin by default.
3483 */
3484 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3485 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
3487 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003488
Willy Tarreau82936582007-11-30 15:20:09 +01003489 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3490 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003491 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3492 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreau82936582007-11-30 15:20:09 +01003493 }
3494
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003495 /* if a default backend was specified, let's find it */
3496 if (curproxy->defbe.name) {
3497 struct proxy *target;
3498
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003499 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3500 if (!target) {
3501 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3502 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003503 cfgerr++;
3504 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003505 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3506 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003507 } else {
3508 free(curproxy->defbe.name);
3509 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003510 /* we force the backend to be present on at least all of
3511 * the frontend's processes.
3512 */
3513 target->bind_proc = curproxy->bind_proc ?
3514 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 }
3516 }
3517
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003518 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003519 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3520 /* map jump target for ACT_SETBE in req_rep chain */
3521 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003522 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003523 struct proxy *target;
3524
Willy Tarreaua496b602006-12-17 23:15:24 +01003525 if (exp->action != ACT_SETBE)
3526 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003527
3528 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3529 if (!target) {
3530 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3531 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003532 cfgerr++;
3533 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003534 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3535 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003536 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003537 } else {
3538 free((void *)exp->replace);
3539 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003540 /* we force the backend to be present on at least all of
3541 * the frontend's processes.
3542 */
3543 target->bind_proc = curproxy->bind_proc ?
3544 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003545 }
3546 }
3547 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003548
3549 /* find the target proxy for 'use_backend' rules */
3550 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003551 struct proxy *target;
3552
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003553 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003554
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003555 if (!target) {
3556 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3557 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003558 cfgerr++;
3559 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003560 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3561 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003562 cfgerr++;
3563 } else {
3564 free((void *)rule->be.name);
3565 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003566 /* we force the backend to be present on at least all of
3567 * the frontend's processes.
3568 */
3569 target->bind_proc = curproxy->bind_proc ?
3570 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003571 }
3572 }
3573
Willy Tarreau2738a142006-07-08 17:28:09 +02003574 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003575 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003576 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003577 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003578 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003579 " | While not properly invalid, you will certainly encounter various problems\n"
3580 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003581 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003583 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003584
Willy Tarreau1fa31262007-12-03 00:36:16 +01003585 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3586 * We must still support older configurations, so let's find out whether those
3587 * parameters have been set or must be copied from contimeouts.
3588 */
3589 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003590 if (!curproxy->timeout.tarpit ||
3591 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003592 /* tarpit timeout not set. We search in the following order:
3593 * default.tarpit, curr.connect, default.connect.
3594 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003595 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003596 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003597 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003598 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003599 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003600 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003601 }
3602 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003603 (!curproxy->timeout.queue ||
3604 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003605 /* queue timeout not set. We search in the following order:
3606 * default.queue, curr.connect, default.connect.
3607 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003608 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003609 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003610 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003611 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003612 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003613 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003614 }
3615 }
3616
Willy Tarreauf3c69202006-07-09 16:42:34 +02003617 if (curproxy->options & PR_O_SSL3_CHK) {
3618 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3619 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3620 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3621 }
3622
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003623 /* The small pools required for the capture lists */
3624 if (curproxy->nb_req_cap)
3625 curproxy->req_cap_pool = create_pool("ptrcap",
3626 curproxy->nb_req_cap * sizeof(char *),
3627 MEM_F_SHARED);
3628 if (curproxy->nb_rsp_cap)
3629 curproxy->rsp_cap_pool = create_pool("ptrcap",
3630 curproxy->nb_rsp_cap * sizeof(char *),
3631 MEM_F_SHARED);
3632
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003633 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3634 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3635 MEM_F_SHARED);
3636
Willy Tarreau86034312006-12-29 00:10:33 +01003637 /* for backwards compatibility with "listen" instances, if
3638 * fullconn is not set but maxconn is set, then maxconn
3639 * is used.
3640 */
3641 if (!curproxy->fullconn)
3642 curproxy->fullconn = curproxy->maxconn;
3643
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 /* first, we will invert the servers list order */
3645 newsrv = NULL;
3646 while (curproxy->srv) {
3647 struct server *next;
3648
3649 next = curproxy->srv->next;
3650 curproxy->srv->next = newsrv;
3651 newsrv = curproxy->srv;
3652 if (!next)
3653 break;
3654 curproxy->srv = next;
3655 }
3656
Willy Tarreau20697042007-11-15 23:26:18 +01003657 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003658 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659
Willy Tarreaub625a082007-11-26 01:15:43 +01003660 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003661 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003662 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003663 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3664 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003665 else
3666 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667
3668 if (curproxy->options & PR_O_LOGASAP)
3669 curproxy->to_log &= ~LW_BYTES;
3670
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003672 * ensure that we're not cross-dressing a TCP server into HTTP.
3673 */
3674 newsrv = curproxy->srv;
3675 while (newsrv != NULL) {
3676 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003677 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3678 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003679 goto err;
3680 }
3681 newsrv = newsrv->next;
3682 }
3683
3684 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003685 * If this server supports a maxconn parameter, it needs a dedicated
3686 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003687 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 */
3689 newsrv = curproxy->srv;
3690 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003691 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 /* Only 'minconn' was specified, or it was higher than or equal
3693 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3694 * this will avoid further useless expensive computations.
3695 */
3696 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003697 } else if (newsrv->maxconn && !newsrv->minconn) {
3698 /* minconn was not specified, so we set it to maxconn */
3699 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003700 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003701 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3702 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003703 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
3705
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003706 if (newsrv->trackit) {
3707 struct proxy *px;
3708 struct server *srv;
3709 char *pname, *sname;
3710
3711 pname = newsrv->trackit;
3712 sname = strrchr(pname, '/');
3713
3714 if (sname)
3715 *sname++ = '\0';
3716 else {
3717 sname = pname;
3718 pname = NULL;
3719 }
3720
3721 if (pname) {
3722 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3723 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003724 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3725 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003726 newsrv->id, pname);
3727 return -1;
3728 }
3729 } else
3730 px = curproxy;
3731
3732 srv = findserver(px, sname);
3733 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003734 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3735 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003736 newsrv->id, sname);
3737 return -1;
3738 }
3739
3740 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003741 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003742 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003743 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003744 newsrv->id, px->id, srv->id);
3745 return -1;
3746 }
3747
3748 if (curproxy != px &&
3749 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003750 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003751 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003752 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003753 newsrv->id, px->id, srv->id);
3754 return -1;
3755 }
3756
3757 newsrv->tracked = srv;
3758 newsrv->tracknext = srv->tracknext;
3759 srv->tracknext = newsrv;
3760
3761 free(newsrv->trackit);
3762 }
3763
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 newsrv = newsrv->next;
3765 }
3766
Willy Tarreaue6b98942007-10-29 01:09:36 +01003767 /* adjust this proxy's listeners */
3768 listener = curproxy->listen;
3769 while (listener) {
3770 if (curproxy->options & PR_O_TCP_NOLING)
3771 listener->options |= LI_O_NOLINGER;
3772 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003773 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003774 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003775 listener->accept = event_accept;
3776 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003777 listener->handler = process_session;
3778
3779 if (curproxy->mode == PR_MODE_HTTP)
3780 listener->analysers |= AN_REQ_HTTP_HDR;
3781
Willy Tarreau9ea05a72009-06-14 12:07:01 +02003782 /* smart accept mode is automatic in HTTP mode */
3783 if ((curproxy->options2 & PR_O2_SMARTACC) ||
3784 (curproxy->mode == PR_MODE_HTTP &&
3785 !(curproxy->no_options2 & PR_O2_SMARTACC)))
3786 listener->options |= LI_O_NOQUICKACK;
3787
Willy Tarreaud869b242009-03-15 14:43:58 +01003788 if (curproxy->tcp_req.inspect_delay ||
3789 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003790 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003791
3792 listener = listener->next;
3793 }
3794
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 curproxy = curproxy->next;
3796 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003797
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 if (cfgerr > 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003799 Alert("Errors found in configuration, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003800 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003802
3803 /*
3804 * Recount currently required checks.
3805 */
3806
3807 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3808 int optnum;
3809
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003810 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3811 if (curproxy->options & cfg_opts[optnum].val)
3812 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003813
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003814 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3815 if (curproxy->options2 & cfg_opts2[optnum].val)
3816 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003817 }
3818
3819 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003820 err:
Willy Tarreau6daf3432008-01-22 16:44:08 +01003821 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822}
3823
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003824/*
3825 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3826 * parsing sessions.
3827 */
3828void cfg_register_keywords(struct cfg_kw_list *kwl)
3829{
3830 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3831}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003833/*
3834 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3835 */
3836void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3837{
3838 LIST_DEL(&kwl->list);
3839 LIST_INIT(&kwl->list);
3840}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841
3842/*
3843 * Local variables:
3844 * c-indent-level: 8
3845 * c-basic-offset: 8
3846 * End:
3847 */