blob: 73446a43218349f7dcc41a77fa66e7c3034d2f8c [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 Tarreaucd7afc02009-07-12 10:03:17 +0200868 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100869 curproxy->source_addr = defproxy.source_addr;
870 }
871
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 curproxy->mode = defproxy.mode;
873 curproxy->logfac1 = defproxy.logfac1;
874 curproxy->logsrv1 = defproxy.logsrv1;
875 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200876 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 curproxy->logfac2 = defproxy.logfac2;
878 curproxy->logsrv2 = defproxy.logsrv2;
879 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200880 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100882 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
883 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200884
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 return 0;
886 }
887 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
888 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100889 /* FIXME-20070101: we should do this too at the end of the
890 * config parsing to free all default values.
891 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200892 free(defproxy.check_req);
893 free(defproxy.cookie_name);
894 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100895 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200896 free(defproxy.capture_name);
897 free(defproxy.monitor_uri);
898 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100899 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200900 free(defproxy.fwdfor_hdr_name);
901 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100902
Willy Tarreaua534fea2008-08-03 12:19:50 +0200903 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
904 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100905
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 /* we cannot free uri_auth because it might already be used */
907 init_default_instance();
908 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100909 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 return 0;
911 }
912 else if (curproxy == NULL) {
913 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
914 return -1;
915 }
916
Willy Tarreau977b8e42006-12-29 14:19:17 +0100917
918 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100920 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100921 int cur_arg;
922
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 if (curproxy == &defproxy) {
924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
925 return -1;
926 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
928 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929
930 if (strchr(args[1], ':') == NULL) {
931 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
932 file, linenum, args[0]);
933 return -1;
934 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100935
936 last_listen = curproxy->listen;
937 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 if (!curproxy->listen)
939 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100940
941 cur_arg = 2;
942 while (*(args[cur_arg])) {
943 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
944#ifdef SO_BINDTODEVICE
945 struct listener *l;
946
947 if (!*args[cur_arg + 1]) {
948 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
949 file, linenum, args[0]);
950 return -1;
951 }
952
953 for (l = curproxy->listen; l != last_listen; l = l->next)
954 l->interface = strdup(args[cur_arg + 1]);
955
956 global.last_checks |= LSTCHK_NETADM;
957
958 cur_arg += 2;
959 continue;
960#else
961 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
962 file, linenum, args[0], args[cur_arg]);
963 return -1;
964#endif
965 }
Willy Tarreaube1b9182009-06-14 18:48:19 +0200966 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
967#ifdef TCP_MAXSEG
968 struct listener *l;
969 int mss;
970
971 if (!*args[cur_arg + 1]) {
972 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
973 file, linenum, args[0]);
974 return -1;
975 }
976
977 mss = str2uic(args[cur_arg + 1]);
978 if (mss < 1 || mss > 65535) {
979 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
980 file, linenum, args[0]);
981 return -1;
982 }
983
984 for (l = curproxy->listen; l != last_listen; l = l->next)
985 l->maxseg = mss;
986
987 cur_arg += 2;
988 continue;
989#else
990 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
991 file, linenum, args[0], args[cur_arg]);
992 return -1;
993#endif
994 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100995 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100996#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100997 struct listener *l;
998
999 for (l = curproxy->listen; l != last_listen; l = l->next)
1000 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001001
1002 cur_arg ++;
1003 continue;
1004#else
1005 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1006 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001007 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001008#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001009 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001010 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001011 file, linenum, args[0]);
1012 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 global.maxsock++;
1015 return 0;
1016 }
1017 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1018 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1019 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1020 file, linenum, args[0]);
1021 return -1;
1022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1024 return 0;
1025
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 /* flush useless bits */
1027 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
1028 return 0;
1029 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001030 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001031 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1032 return 0;
1033
Willy Tarreau1c47f852006-07-09 08:22:27 +02001034 if (!*args[1]) {
1035 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1036 file, linenum, args[0]);
1037 return -1;
1038 }
1039
Willy Tarreaua534fea2008-08-03 12:19:50 +02001040 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001041 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001042 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001043 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001044 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1045
1046 return 0;
1047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1049 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1050 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1051 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1052 else {
1053 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
1054 return -1;
1055 }
1056 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001057 else if (!strcmp(args[0], "id")) {
1058 struct proxy *target;
1059
1060 if (curproxy == &defproxy) {
1061 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1062 file, linenum, args[0]);
1063 return -1;
1064 }
1065
1066 if (!*args[1]) {
1067 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1068 file, linenum, args[0]);
1069 return -1;
1070 }
1071
1072 curproxy->uuid = atol(args[1]);
1073
1074 if (curproxy->uuid < 1001) {
1075 Alert("parsing [%s:%d]: custom id has to be > 1000",
1076 file, linenum);
1077 return -1;
1078 }
1079
1080 for (target = proxy; target; target = target->next)
1081 if (curproxy != target && curproxy->uuid == target->uuid) {
1082 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1083 file, linenum, curproxy->id, target->id);
1084 return -1;
1085 }
1086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1088 curproxy->state = PR_STSTOPPED;
1089 }
1090 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1091 curproxy->state = PR_STNEW;
1092 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001093 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1094 int cur_arg = 1;
1095 unsigned int set = 0;
1096
1097 while (*args[cur_arg]) {
1098 int u;
1099 if (strcmp(args[cur_arg], "all") == 0) {
1100 set = 0;
1101 break;
1102 }
1103 else if (strcmp(args[cur_arg], "odd") == 0) {
1104 set |= 0x55555555;
1105 }
1106 else if (strcmp(args[cur_arg], "even") == 0) {
1107 set |= 0xAAAAAAAA;
1108 }
1109 else {
1110 u = str2uic(args[cur_arg]);
1111 if (u < 1 || u > 32) {
1112 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1113 file, linenum, args[0]);
1114 return -1;
1115 }
1116 if (u > global.nbproc) {
1117 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1118 file, linenum, args[0]);
1119 }
1120 set |= 1 << (u - 1);
1121 }
1122 cur_arg++;
1123 }
1124 curproxy->bind_proc = set;
1125 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001126 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001127 if (curproxy == &defproxy) {
1128 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1129 return -1;
1130 }
1131
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001132 err = invalid_char(args[1]);
1133 if (err) {
1134 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1135 file, linenum, *err, args[1]);
1136 return -1;
1137 }
1138
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001139 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1140 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1141 file, linenum, args[1]);
1142 return -1;
1143 }
1144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1146 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
Willy Tarreau977b8e42006-12-29 14:19:17 +01001148 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1149 return 0;
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 if (*(args[1]) == 0) {
1152 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1153 file, linenum, args[0]);
1154 return -1;
1155 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001156
1157 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158 curproxy->cookie_name = strdup(args[1]);
1159 curproxy->cookie_len = strlen(curproxy->cookie_name);
1160
1161 cur_arg = 2;
1162 while (*(args[cur_arg])) {
1163 if (!strcmp(args[cur_arg], "rewrite")) {
1164 curproxy->options |= PR_O_COOK_RW;
1165 }
1166 else if (!strcmp(args[cur_arg], "indirect")) {
1167 curproxy->options |= PR_O_COOK_IND;
1168 }
1169 else if (!strcmp(args[cur_arg], "insert")) {
1170 curproxy->options |= PR_O_COOK_INS;
1171 }
1172 else if (!strcmp(args[cur_arg], "nocache")) {
1173 curproxy->options |= PR_O_COOK_NOC;
1174 }
1175 else if (!strcmp(args[cur_arg], "postonly")) {
1176 curproxy->options |= PR_O_COOK_POST;
1177 }
1178 else if (!strcmp(args[cur_arg], "prefix")) {
1179 curproxy->options |= PR_O_COOK_PFX;
1180 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001181 else if (!strcmp(args[cur_arg], "domain")) {
1182 if (!*args[cur_arg + 1]) {
1183 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1184 file, linenum, args[cur_arg]);
1185 return -1;
1186 }
1187
1188 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1189 /* rfc2109, 4.3.2 Rejecting Cookies */
1190 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1191 " dots or does not start with a dot.\n",
1192 file, linenum, args[cur_arg + 1]);
1193 return -1;
1194 }
1195
1196 err = invalid_domainchar(args[cur_arg + 1]);
1197 if (err) {
1198 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1199 file, linenum, *err, args[cur_arg + 1]);
1200 return -1;
1201 }
1202
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001203 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001204 cur_arg++;
1205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001207 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 file, linenum, args[0]);
1209 return -1;
1210 }
1211 cur_arg++;
1212 }
1213 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1214 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1215 file, linenum);
1216 return -1;
1217 }
1218
1219 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1220 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1221 file, linenum);
1222 return -1;
1223 }
1224 }/* end else if (!strcmp(args[0], "cookie")) */
1225 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001226
Willy Tarreau977b8e42006-12-29 14:19:17 +01001227 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1228 return 0;
1229
Willy Tarreaubaaee002006-06-26 02:48:02 +02001230 if (*(args[5]) == 0) {
1231 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1232 file, linenum, args[0]);
1233 return -1;
1234 }
1235 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001236 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001237 curproxy->appsession_name = strdup(args[1]);
1238 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1239 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001240 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1241 if (err) {
1242 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1243 file, linenum, *err, args[0]);
1244 return -1;
1245 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001246 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001247
Willy Tarreau51041c72007-09-09 21:56:53 +02001248 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 return -1;
1251 }
1252 } /* Url App Session */
1253 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001254 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1255 return 0;
1256
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 if (*(args[4]) == 0) {
1259 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1260 file, linenum, args[0]);
1261 return -1;
1262 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001263 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 curproxy->capture_name = strdup(args[2]);
1265 curproxy->capture_namelen = strlen(curproxy->capture_name);
1266 curproxy->capture_len = atol(args[4]);
1267 if (curproxy->capture_len >= CAPTURE_LEN) {
1268 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1269 file, linenum, CAPTURE_LEN - 1);
1270 curproxy->capture_len = CAPTURE_LEN - 1;
1271 }
1272 curproxy->to_log |= LW_COOKIE;
1273 }
1274 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1275 struct cap_hdr *hdr;
1276
1277 if (curproxy == &defproxy) {
1278 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1279 return -1;
1280 }
1281
1282 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1283 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1284 file, linenum, args[0], args[1]);
1285 return -1;
1286 }
1287
1288 hdr = calloc(sizeof(struct cap_hdr), 1);
1289 hdr->next = curproxy->req_cap;
1290 hdr->name = strdup(args[3]);
1291 hdr->namelen = strlen(args[3]);
1292 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001293 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 hdr->index = curproxy->nb_req_cap++;
1295 curproxy->req_cap = hdr;
1296 curproxy->to_log |= LW_REQHDR;
1297 }
1298 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1299 struct cap_hdr *hdr;
1300
1301 if (curproxy == &defproxy) {
1302 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1303 return -1;
1304 }
1305
1306 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1307 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1308 file, linenum, args[0], args[1]);
1309 return -1;
1310 }
1311 hdr = calloc(sizeof(struct cap_hdr), 1);
1312 hdr->next = curproxy->rsp_cap;
1313 hdr->name = strdup(args[3]);
1314 hdr->namelen = strlen(args[3]);
1315 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001316 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 hdr->index = curproxy->nb_rsp_cap++;
1318 curproxy->rsp_cap = hdr;
1319 curproxy->to_log |= LW_RSPHDR;
1320 }
1321 else {
1322 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1323 file, linenum, args[0]);
1324 return -1;
1325 }
1326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1329 return 0;
1330
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331 if (*(args[1]) == 0) {
1332 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1333 file, linenum, args[0]);
1334 return -1;
1335 }
1336 curproxy->conn_retries = atol(args[1]);
1337 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001338 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1339 int pol = ACL_COND_NONE;
1340 struct acl_cond *cond;
1341
Willy Tarreaub099aca2008-10-12 17:26:37 +02001342 if (curproxy == &defproxy) {
1343 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1344 return -1;
1345 }
1346
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001347 if (!strcmp(args[1], "if"))
1348 pol = ACL_COND_IF;
1349 else if (!strcmp(args[1], "unless"))
1350 pol = ACL_COND_UNLESS;
1351
1352 if (pol == ACL_COND_NONE) {
1353 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1354 file, linenum, args[0]);
1355 return -1;
1356 }
1357
1358 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1359 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1360 file, linenum);
1361 return -1;
1362 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001363 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001364 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001365 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001366 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001367 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001368 else if (!strcmp(args[0], "redirect")) {
1369 int pol = ACL_COND_NONE;
1370 struct acl_cond *cond;
1371 struct redirect_rule *rule;
1372 int cur_arg;
1373 int type = REDIRECT_TYPE_NONE;
1374 int code = 302;
1375 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001376 char *cookie = NULL;
1377 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001378 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001379
1380 cur_arg = 1;
1381 while (*(args[cur_arg])) {
1382 if (!strcmp(args[cur_arg], "location")) {
1383 if (!*args[cur_arg + 1]) {
1384 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1385 file, linenum, args[0], args[cur_arg]);
1386 return -1;
1387 }
1388
1389 type = REDIRECT_TYPE_LOCATION;
1390 cur_arg++;
1391 destination = args[cur_arg];
1392 }
1393 else if (!strcmp(args[cur_arg], "prefix")) {
1394 if (!*args[cur_arg + 1]) {
1395 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1396 file, linenum, args[0], args[cur_arg]);
1397 return -1;
1398 }
1399
1400 type = REDIRECT_TYPE_PREFIX;
1401 cur_arg++;
1402 destination = args[cur_arg];
1403 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001404 else if (!strcmp(args[cur_arg], "set-cookie")) {
1405 if (!*args[cur_arg + 1]) {
1406 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1407 file, linenum, args[0], args[cur_arg]);
1408 return -1;
1409 }
1410
1411 cur_arg++;
1412 cookie = args[cur_arg];
1413 cookie_set = 1;
1414 }
1415 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1416 if (!*args[cur_arg + 1]) {
1417 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1418 file, linenum, args[0], args[cur_arg]);
1419 return -1;
1420 }
1421
1422 cur_arg++;
1423 cookie = args[cur_arg];
1424 cookie_set = 0;
1425 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001426 else if (!strcmp(args[cur_arg],"code")) {
1427 if (!*args[cur_arg + 1]) {
1428 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1429 file, linenum, args[0]);
1430 return -1;
1431 }
1432 cur_arg++;
1433 code = atol(args[cur_arg]);
1434 if (code < 301 || code > 303) {
1435 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1436 file, linenum, args[0], code);
1437 return -1;
1438 }
1439 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001440 else if (!strcmp(args[cur_arg],"drop-query")) {
1441 flags |= REDIRECT_FLAG_DROP_QS;
1442 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001443 else if (!strcmp(args[cur_arg], "if")) {
1444 pol = ACL_COND_IF;
1445 cur_arg++;
1446 break;
1447 }
1448 else if (!strcmp(args[cur_arg], "unless")) {
1449 pol = ACL_COND_UNLESS;
1450 cur_arg++;
1451 break;
1452 }
1453 else {
1454 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1455 file, linenum, args[0], args[cur_arg]);
1456 return -1;
1457 }
1458 cur_arg++;
1459 }
1460
1461 if (type == REDIRECT_TYPE_NONE) {
1462 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1463 file, linenum, args[0]);
1464 return -1;
1465 }
1466
1467 if (pol == ACL_COND_NONE) {
1468 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1469 file, linenum, args[0]);
1470 return -1;
1471 }
1472
1473 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001474 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001475 file, linenum, args[0]);
1476 return -1;
1477 }
1478
Willy Tarreaua9802632008-07-25 19:13:19 +02001479 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001480 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001481 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1482 rule->cond = cond;
1483 rule->rdr_str = strdup(destination);
1484 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001485 if (cookie) {
1486 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1487 * a clear consists in appending "; Max-Age=0" at the end.
1488 */
1489 rule->cookie_len = strlen(cookie);
1490 if (cookie_set)
1491 rule->cookie_str = strdup(cookie);
1492 else {
1493 rule->cookie_str = malloc(rule->cookie_len + 12);
1494 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1495 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1496 rule->cookie_len += 11;
1497 }
1498 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001499 rule->type = type;
1500 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001501 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001502 LIST_INIT(&rule->list);
1503 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001504 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001505 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001506 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001507 int pol = ACL_COND_NONE;
1508 struct acl_cond *cond;
1509 struct switching_rule *rule;
1510
Willy Tarreaub099aca2008-10-12 17:26:37 +02001511 if (curproxy == &defproxy) {
1512 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1513 return -1;
1514 }
1515
Willy Tarreau55ea7572007-06-17 19:56:27 +02001516 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1517 return 0;
1518
1519 if (*(args[1]) == 0) {
1520 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1521 return -1;
1522 }
1523
1524 if (!strcmp(args[2], "if"))
1525 pol = ACL_COND_IF;
1526 else if (!strcmp(args[2], "unless"))
1527 pol = ACL_COND_UNLESS;
1528
1529 if (pol == ACL_COND_NONE) {
1530 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1531 file, linenum, args[0]);
1532 return -1;
1533 }
1534
1535 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001536 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001537 file, linenum);
1538 return -1;
1539 }
1540
Willy Tarreaua9802632008-07-25 19:13:19 +02001541 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001542 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001543 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001544 struct acl *acl;
1545 const char *name;
1546
1547 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1548 name = acl ? acl->name : "(unknown)";
1549 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1550 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001551 }
1552
Willy Tarreau55ea7572007-06-17 19:56:27 +02001553 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1554 rule->cond = cond;
1555 rule->be.name = strdup(args[1]);
1556 LIST_INIT(&rule->list);
1557 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001560 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1561 return 0;
1562
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1564 curproxy->uri_auth = NULL; /* we must detach from the default config */
1565
1566 if (*(args[1]) == 0) {
1567 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1568 return -1;
1569 } else if (!strcmp(args[1], "uri")) {
1570 if (*(args[2]) == 0) {
1571 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1572 return -1;
1573 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1574 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1575 return -1;
1576 }
1577 } else if (!strcmp(args[1], "realm")) {
1578 if (*(args[2]) == 0) {
1579 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1580 return -1;
1581 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1582 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1583 return -1;
1584 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001585 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001586 unsigned interval;
1587
1588 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1589 if (err) {
1590 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1591 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001592 return -1;
1593 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1594 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1595 return -1;
1596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 } else if (!strcmp(args[1], "auth")) {
1598 if (*(args[2]) == 0) {
1599 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1600 return -1;
1601 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1602 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1603 return -1;
1604 }
1605 } else if (!strcmp(args[1], "scope")) {
1606 if (*(args[2]) == 0) {
1607 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1608 return -1;
1609 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1610 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1611 return -1;
1612 }
1613 } else if (!strcmp(args[1], "enable")) {
1614 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1615 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1616 return -1;
1617 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001618 } else if (!strcmp(args[1], "hide-version")) {
1619 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1620 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1621 return -1;
1622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001624 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 file, linenum, args[0]);
1626 return -1;
1627 }
1628 }
1629 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001630 int optnum;
1631
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001632 if (*(args[1]) == '\0') {
1633 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1634 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 return -1;
1636 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001637
1638 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1639 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1640 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1641 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001642
Willy Tarreau3842f002009-06-14 11:39:52 +02001643 curproxy->no_options &= ~cfg_opts[optnum].val;
1644 curproxy->options &= ~cfg_opts[optnum].val;
1645
1646 switch (kwm) {
1647 case KWM_STD:
1648 curproxy->options |= cfg_opts[optnum].val;
1649 break;
1650 case KWM_NO:
1651 curproxy->no_options |= cfg_opts[optnum].val;
1652 break;
1653 case KWM_DEF: /* already cleared */
1654 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001655 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001656
Willy Tarreau13943ab2006-12-31 00:24:10 +01001657 return 0;
1658 }
1659 }
1660
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001661 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1662 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1663 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1664 return 0;
1665
Willy Tarreau3842f002009-06-14 11:39:52 +02001666 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1667 curproxy->options2 &= ~cfg_opts2[optnum].val;
1668
1669 switch (kwm) {
1670 case KWM_STD:
1671 curproxy->options2 |= cfg_opts2[optnum].val;
1672 break;
1673 case KWM_NO:
1674 curproxy->no_options2 |= cfg_opts2[optnum].val;
1675 break;
1676 case KWM_DEF: /* already cleared */
1677 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001678 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001679 return 0;
1680 }
1681 }
1682
Willy Tarreau3842f002009-06-14 11:39:52 +02001683 if (kwm != KWM_STD) {
1684 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001685 file, linenum, args[1]);
1686 return -1;
1687 }
1688
Willy Tarreau13943ab2006-12-31 00:24:10 +01001689 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 /* generate a complete HTTP log */
1691 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1692 else if (!strcmp(args[1], "tcplog"))
1693 /* generate a detailed TCP log */
1694 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001695 else if (!strcmp(args[1], "tcpka")) {
1696 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001697 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1698 return 0;
1699
1700 if (curproxy->cap & PR_CAP_FE)
1701 curproxy->options |= PR_O_TCP_CLI_KA;
1702 if (curproxy->cap & PR_CAP_BE)
1703 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 }
1705 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1707 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001709 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001710 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001711 curproxy->options &= ~PR_O_SMTP_CHK;
1712 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 if (!*args[2]) { /* no argument */
1714 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1715 curproxy->check_len = strlen(DEF_CHECK_REQ);
1716 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001717 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 curproxy->check_req = (char *)malloc(reqlen);
1719 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1720 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1721 } else { /* more arguments : METHOD URI [HTTP_VER] */
1722 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1723 if (*args[4])
1724 reqlen += strlen(args[4]);
1725 else
1726 reqlen += strlen("HTTP/1.0");
1727
1728 curproxy->check_req = (char *)malloc(reqlen);
1729 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1730 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1731 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001732 }
1733 else if (!strcmp(args[1], "ssl-hello-chk")) {
1734 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1736 return 0;
1737
Willy Tarreaua534fea2008-08-03 12:19:50 +02001738 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001739 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001740 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001741 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 }
Willy Tarreau23677902007-05-08 23:50:35 +02001743 else if (!strcmp(args[1], "smtpchk")) {
1744 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001745 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001746 curproxy->options &= ~PR_O_HTTP_CHK;
1747 curproxy->options &= ~PR_O_SSL3_CHK;
1748 curproxy->options |= PR_O_SMTP_CHK;
1749
1750 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1751 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1752 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1753 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1754 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1755 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1756 curproxy->check_req = (char *)malloc(reqlen);
1757 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1758 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1759 } else {
1760 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1761 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1762 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1763 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1764 }
1765 }
1766 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001767 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001768 int cur_arg;
1769
1770 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1771 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001772 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001773
1774 curproxy->options |= PR_O_FWDFOR;
1775
1776 free(curproxy->fwdfor_hdr_name);
1777 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1778 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1779
1780 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1781 cur_arg = 2;
1782 while (*(args[cur_arg])) {
1783 if (!strcmp(args[cur_arg], "except")) {
1784 /* suboption except - needs additional argument for it */
1785 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1786 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1787 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001788 return -1;
1789 }
1790 /* flush useless bits */
1791 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001792 cur_arg += 2;
1793 } else if (!strcmp(args[cur_arg], "header")) {
1794 /* suboption header - needs additional argument for it */
1795 if (*(args[cur_arg+1]) == 0) {
1796 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1797 file, linenum, args[0], args[1], args[cur_arg]);
1798 return -1;
1799 }
1800 free(curproxy->fwdfor_hdr_name);
1801 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1802 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1803 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001804 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001805 /* unknown suboption - catchall */
1806 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1807 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001808 return -1;
1809 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001810 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001811 }
Maik Broemme2850cb42009-04-17 18:53:21 +02001812 else if (!strcmp(args[1], "originalto")) {
1813 int cur_arg;
1814
1815 /* insert x-original-to field, but not for the IP address listed as an except.
1816 * set default options (ie: bitfield, header name, etc)
1817 */
1818
1819 curproxy->options |= PR_O_ORGTO;
1820
1821 free(curproxy->orgto_hdr_name);
1822 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
1823 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
1824
1825 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1826 cur_arg = 2;
1827 while (*(args[cur_arg])) {
1828 if (!strcmp(args[cur_arg], "except")) {
1829 /* suboption except - needs additional argument for it */
1830 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
1831 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1832 file, linenum, args[0], args[1], args[cur_arg]);
1833 return -1;
1834 }
1835 /* flush useless bits */
1836 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
1837 cur_arg += 2;
1838 } else if (!strcmp(args[cur_arg], "header")) {
1839 /* suboption header - needs additional argument for it */
1840 if (*(args[cur_arg+1]) == 0) {
1841 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1842 file, linenum, args[0], args[1], args[cur_arg]);
1843 return -1;
1844 }
1845 free(curproxy->orgto_hdr_name);
1846 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
1847 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
1848 cur_arg += 2;
1849 } else {
1850 /* unknown suboption - catchall */
1851 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1852 file, linenum, args[0], args[1]);
1853 return -1;
1854 }
1855 } /* end while loop */
1856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 else {
1858 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1859 return -1;
1860 }
1861 return 0;
1862 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001863 else if (!strcmp(args[0], "default_backend")) {
1864 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1865 return 0;
1866
1867 if (*(args[1]) == 0) {
1868 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1869 return -1;
1870 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001871 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001872 curproxy->defbe.name = strdup(args[1]);
1873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1876 return 0;
1877
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001878 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1879 file, linenum, args[0]);
1880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 /* enable reconnections to dispatch */
1882 curproxy->options |= PR_O_REDISP;
1883 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001884 else if (!strcmp(args[0], "http-check")) {
1885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1886 return 0;
1887
1888 if (strcmp(args[1], "disable-on-404") == 0) {
1889 /* enable a graceful server shutdown on an HTTP 404 response */
1890 curproxy->options |= PR_O_DISABLE404;
1891 }
1892 else {
1893 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1894 return -1;
1895 }
1896 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001897 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001898 if (curproxy == &defproxy) {
1899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1900 return -1;
1901 }
1902
Willy Tarreaub80c2302007-11-30 20:51:32 +01001903 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1904 return 0;
1905
1906 if (strcmp(args[1], "fail") == 0) {
1907 /* add a condition to fail monitor requests */
1908 int pol = ACL_COND_NONE;
1909 struct acl_cond *cond;
1910
1911 if (!strcmp(args[2], "if"))
1912 pol = ACL_COND_IF;
1913 else if (!strcmp(args[2], "unless"))
1914 pol = ACL_COND_UNLESS;
1915
1916 if (pol == ACL_COND_NONE) {
1917 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1918 file, linenum, args[0], args[1]);
1919 return -1;
1920 }
1921
1922 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1923 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1924 file, linenum, args[0], args[1]);
1925 return -1;
1926 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001927 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001928 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001929 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1930 }
1931 else {
1932 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1933 return -1;
1934 }
1935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936#ifdef TPROXY
1937 else if (!strcmp(args[0], "transparent")) {
1938 /* enable transparent proxy connections */
1939 curproxy->options |= PR_O_TRANSP;
1940 }
1941#endif
1942 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1944 return 0;
1945
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 if (*(args[1]) == 0) {
1947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1948 return -1;
1949 }
1950 curproxy->maxconn = atol(args[1]);
1951 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001952 else if (!strcmp(args[0], "backlog")) { /* backlog */
1953 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1954 return 0;
1955
1956 if (*(args[1]) == 0) {
1957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1958 return -1;
1959 }
1960 curproxy->backlog = atol(args[1]);
1961 }
Willy Tarreau86034312006-12-29 00:10:33 +01001962 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1964 return 0;
1965
Willy Tarreau86034312006-12-29 00:10:33 +01001966 if (*(args[1]) == 0) {
1967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1968 return -1;
1969 }
1970 curproxy->fullconn = atol(args[1]);
1971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1973 if (*(args[1]) == 0) {
1974 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1975 return -1;
1976 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001977 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1978 if (err) {
1979 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1980 file, linenum, *err);
1981 return -1;
1982 }
1983 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 }
1985 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1986 if (curproxy == &defproxy) {
1987 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1988 return -1;
1989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001990 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1991 return 0;
1992
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 if (strchr(args[1], ':') == NULL) {
1994 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1995 return -1;
1996 }
1997 curproxy->dispatch_addr = *str2sa(args[1]);
1998 }
1999 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2001 return 0;
2002
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002003 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002004 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2005 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
2006 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
2009 else if (!strcmp(args[0], "server")) { /* server address */
2010 int cur_arg;
2011 char *rport;
2012 char *raddr;
2013 short realport;
2014 int do_check;
2015
2016 if (curproxy == &defproxy) {
2017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2018 return -1;
2019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002020 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2021 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022
2023 if (!*args[2]) {
2024 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2025 file, linenum, args[0]);
2026 return -1;
2027 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002028
2029 err = invalid_char(args[1]);
2030 if (err) {
2031 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2032 file, linenum, *err, args[1]);
2033 return -1;
2034 }
2035
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2037 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2038 return -1;
2039 }
2040
2041 /* the servers are linked backwards first */
2042 newsrv->next = curproxy->srv;
2043 curproxy->srv = newsrv;
2044 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002045 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046
2047 LIST_INIT(&newsrv->pendconns);
2048 do_check = 0;
2049 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002050 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 newsrv->id = strdup(args[1]);
2052
2053 /* several ways to check the port component :
2054 * - IP => port=+0, relative
2055 * - IP: => port=+0, relative
2056 * - IP:N => port=N, absolute
2057 * - IP:+N => port=+N, relative
2058 * - IP:-N => port=-N, relative
2059 */
2060 raddr = strdup(args[2]);
2061 rport = strchr(raddr, ':');
2062 if (rport) {
2063 *rport++ = 0;
2064 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002065 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 newsrv->state |= SRV_MAPPORTS;
2067 } else {
2068 realport = 0;
2069 newsrv->state |= SRV_MAPPORTS;
2070 }
2071
2072 newsrv->addr = *str2sa(raddr);
2073 newsrv->addr.sin_port = htons(realport);
2074 free(raddr);
2075
2076 newsrv->curfd = -1; /* no health-check in progress */
2077 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002078 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2079 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 newsrv->rise = DEF_RISETIME;
2081 newsrv->fall = DEF_FALLTIME;
2082 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002083 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002084 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002085 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002086
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 cur_arg = 3;
2088 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002089 if (!strcmp(args[cur_arg], "id")) {
2090 struct server *target;
2091
2092 if (!*args[cur_arg + 1]) {
2093 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2094 file, linenum, args[cur_arg]);
2095 return -1;
2096 }
2097
2098 newsrv->puid = atol(args[cur_arg + 1]);
2099
2100 if (newsrv->puid< 1001) {
2101 Alert("parsing [%s:%d]: custom id has to be > 1000",
2102 file, linenum);
2103 return -1;
2104 }
2105
2106 for (target = proxy->srv; target; target = target->next)
2107 if (newsrv != target && newsrv->puid == target->puid) {
2108 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2109 file, linenum, newsrv->id, target->id);
2110 return -1;
2111 }
2112 cur_arg += 2;
2113 }
2114 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 newsrv->cookie = strdup(args[cur_arg + 1]);
2116 newsrv->cklen = strlen(args[cur_arg + 1]);
2117 cur_arg += 2;
2118 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002119 else if (!strcmp(args[cur_arg], "redir")) {
2120 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2121 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2122 cur_arg += 2;
2123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 else if (!strcmp(args[cur_arg], "rise")) {
2125 newsrv->rise = atol(args[cur_arg + 1]);
2126 newsrv->health = newsrv->rise;
2127 cur_arg += 2;
2128 }
2129 else if (!strcmp(args[cur_arg], "fall")) {
2130 newsrv->fall = atol(args[cur_arg + 1]);
2131 cur_arg += 2;
2132 }
2133 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002134 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2135 if (err) {
2136 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2137 file, linenum, *err, newsrv->id);
2138 return -1;
2139 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002140 if (val <= 0) {
2141 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2142 file, linenum, val, args[cur_arg], newsrv->id);
2143 return -1;
2144 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002145 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 cur_arg += 2;
2147 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002148 else if (!strcmp(args[cur_arg], "fastinter")) {
2149 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2150 if (err) {
2151 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2152 file, linenum, *err, newsrv->id);
2153 return -1;
2154 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002155 if (val <= 0) {
2156 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2157 file, linenum, val, args[cur_arg], newsrv->id);
2158 return -1;
2159 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002160 newsrv->fastinter = val;
2161 cur_arg += 2;
2162 }
2163 else if (!strcmp(args[cur_arg], "downinter")) {
2164 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2165 if (err) {
2166 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2167 file, linenum, *err, newsrv->id);
2168 return -1;
2169 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002170 if (val <= 0) {
2171 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2172 file, linenum, val, args[cur_arg], newsrv->id);
2173 return -1;
2174 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002175 newsrv->downinter = val;
2176 cur_arg += 2;
2177 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002178 else if (!strcmp(args[cur_arg], "addr")) {
2179 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002180 cur_arg += 2;
2181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002182 else if (!strcmp(args[cur_arg], "port")) {
2183 newsrv->check_port = atol(args[cur_arg + 1]);
2184 cur_arg += 2;
2185 }
2186 else if (!strcmp(args[cur_arg], "backup")) {
2187 newsrv->state |= SRV_BACKUP;
2188 cur_arg ++;
2189 }
2190 else if (!strcmp(args[cur_arg], "weight")) {
2191 int w;
2192 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002193 if (w < 0 || w > 256) {
2194 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 file, linenum, newsrv->id, w);
2196 return -1;
2197 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002198 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 cur_arg += 2;
2200 }
2201 else if (!strcmp(args[cur_arg], "minconn")) {
2202 newsrv->minconn = atol(args[cur_arg + 1]);
2203 cur_arg += 2;
2204 }
2205 else if (!strcmp(args[cur_arg], "maxconn")) {
2206 newsrv->maxconn = atol(args[cur_arg + 1]);
2207 cur_arg += 2;
2208 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002209 else if (!strcmp(args[cur_arg], "maxqueue")) {
2210 newsrv->maxqueue = atol(args[cur_arg + 1]);
2211 cur_arg += 2;
2212 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002213 else if (!strcmp(args[cur_arg], "slowstart")) {
2214 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002215 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002216 if (err) {
2217 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2218 file, linenum, *err, newsrv->id);
2219 return -1;
2220 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002221 if (val <= 0) {
2222 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2223 file, linenum, val, args[cur_arg], newsrv->id);
2224 return -1;
2225 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002226 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002227 cur_arg += 2;
2228 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002229 else if (!strcmp(args[cur_arg], "track")) {
2230
2231 if (!*args[cur_arg + 1]) {
2232 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2233 file, linenum);
2234 return -1;
2235 }
2236
2237 newsrv->trackit = strdup(args[cur_arg + 1]);
2238
2239 cur_arg += 2;
2240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 else if (!strcmp(args[cur_arg], "check")) {
2242 global.maxsock++;
2243 do_check = 1;
2244 cur_arg += 1;
2245 }
2246 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002247 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002249#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002250 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002251 file, linenum, "source", "usesrc");
2252#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002253 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002255#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 return -1;
2257 }
2258 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002259 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2260
2261 if (port_low != port_high) {
2262 int i;
2263 if (port_low <= 0 || port_low > 65535 ||
2264 port_high <= 0 || port_high > 65535 ||
2265 port_low > port_high) {
2266 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2267 file, linenum, port_low, port_high);
2268 return -1;
2269 }
2270 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2271 for (i = 0; i < newsrv->sport_range->size; i++)
2272 newsrv->sport_range->ports[i] = port_low + i;
2273 }
2274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002276 while (*(args[cur_arg])) {
2277 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002278#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2279#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002280 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2281 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2282 file, linenum, "usesrc", "source");
2283 return -1;
2284 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002285#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002286 if (!*args[cur_arg + 1]) {
2287 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2288 file, linenum, "usesrc");
2289 return -1;
2290 }
2291 if (!strcmp(args[cur_arg + 1], "client")) {
2292 newsrv->state |= SRV_TPROXY_CLI;
2293 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2294 newsrv->state |= SRV_TPROXY_CIP;
2295 } else {
2296 newsrv->state |= SRV_TPROXY_ADDR;
2297 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2298 }
2299 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002300#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002301 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002302#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002303 cur_arg += 2;
2304 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002305#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002306 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002307 file, linenum, "usesrc");
2308 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002309#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2310 } /* "usesrc" */
2311
2312 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2313#ifdef SO_BINDTODEVICE
2314 if (!*args[cur_arg + 1]) {
2315 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2316 file, linenum, args[0]);
2317 return -1;
2318 }
2319 if (newsrv->iface_name)
2320 free(newsrv->iface_name);
2321
2322 newsrv->iface_name = strdup(args[cur_arg + 1]);
2323 newsrv->iface_len = strlen(newsrv->iface_name);
2324 global.last_checks |= LSTCHK_NETADM;
2325#else
2326 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2327 file, linenum, args[0], args[cur_arg]);
2328 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002329#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002330 cur_arg += 2;
2331 continue;
2332 }
2333 /* this keyword in not an option of "source" */
2334 break;
2335 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002337 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2338 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2339 file, linenum, "usesrc", "source");
2340 return -1;
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002343 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 +02002344 file, linenum, newsrv->id);
2345 return -1;
2346 }
2347 }
2348
2349 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002350 if (newsrv->trackit) {
2351 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2352 file, linenum);
2353 return -1;
2354 }
2355
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002356 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2357 newsrv->check_port = newsrv->check_addr.sin_port;
2358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2360 newsrv->check_port = realport; /* by default */
2361 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002362 /* not yet valid, because no port was set on
2363 * the server either. We'll check if we have
2364 * a known port on the first listener.
2365 */
2366 struct listener *l;
2367 l = curproxy->listen;
2368 if (l) {
2369 int port;
2370 port = (l->addr.ss_family == AF_INET6)
2371 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2372 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2373 newsrv->check_port = port;
2374 }
2375 }
2376 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2378 file, linenum, newsrv->id);
2379 return -1;
2380 }
2381 newsrv->state |= SRV_CHECKED;
2382 }
2383
2384 if (newsrv->state & SRV_BACKUP)
2385 curproxy->srv_bck++;
2386 else
2387 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002388
2389 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002392 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 int facility;
2394
2395 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2396 curproxy->logfac1 = global.logfac1;
2397 curproxy->logsrv1 = global.logsrv1;
2398 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002399 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 curproxy->logfac2 = global.logfac2;
2401 curproxy->logsrv2 = global.logsrv2;
2402 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002403 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002406 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407
2408 facility = get_log_facility(args[2]);
2409 if (facility < 0) {
2410 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2411 exit(1);
2412 }
2413
2414 level = 7; /* max syslog level = debug */
2415 if (*(args[3])) {
2416 level = get_log_level(args[3]);
2417 if (level < 0) {
2418 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2419 exit(1);
2420 }
2421 }
2422
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002423 minlvl = 0; /* limit syslog level to this level (emerg) */
2424 if (*(args[4])) {
2425 minlvl = get_log_level(args[4]);
2426 if (level < 0) {
2427 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2428 exit(1);
2429 }
2430 }
2431
Robert Tsai81ae1952007-12-05 10:47:29 +01002432 if (args[1][0] == '/') {
2433 logsrv.u.addr.sa_family = AF_UNIX;
2434 logsrv.u.un = *str2sun(args[1]);
2435 } else {
2436 logsrv.u.addr.sa_family = AF_INET;
2437 logsrv.u.in = *str2sa(args[1]);
2438 if (!logsrv.u.in.sin_port) {
2439 logsrv.u.in.sin_port =
2440 htons(SYSLOG_PORT);
2441 }
2442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443
2444 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002445 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 curproxy->logfac1 = facility;
2447 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002448 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
2450 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002451 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 curproxy->logfac2 = facility;
2453 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002454 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 else {
2457 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2458 return -1;
2459 }
2460 }
2461 else {
2462 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2463 file, linenum);
2464 return -1;
2465 }
2466 }
2467 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002468 int cur_arg;
2469
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2471 return 0;
2472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002474 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2475 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 return -1;
2477 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002478
2479 /* we must first clear any optional default setting */
2480 curproxy->options &= ~PR_O_TPXY_MASK;
2481 free(curproxy->iface_name);
2482 curproxy->iface_name = NULL;
2483 curproxy->iface_len = 0;
2484
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 curproxy->source_addr = *str2sa(args[1]);
2486 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002487
2488 cur_arg = 2;
2489 while (*(args[cur_arg])) {
2490 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002491#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2492#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002493 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2494 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2495 file, linenum, "usesrc");
2496 return -1;
2497 }
2498#endif
2499 if (!*args[cur_arg + 1]) {
2500 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2501 file, linenum, "usesrc");
2502 return -1;
2503 }
2504
2505 if (!strcmp(args[cur_arg + 1], "client")) {
2506 curproxy->options |= PR_O_TPXY_CLI;
2507 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2508 curproxy->options |= PR_O_TPXY_CIP;
2509 } else {
2510 curproxy->options |= PR_O_TPXY_ADDR;
2511 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2512 }
2513 global.last_checks |= LSTCHK_NETADM;
2514#if !defined(CONFIG_HAP_LINUX_TPROXY)
2515 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002516#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002517#else /* no TPROXY support */
2518 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002519 file, linenum, "usesrc");
2520 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002521#endif
2522 cur_arg += 2;
2523 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002524 }
2525
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002526 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2527#ifdef SO_BINDTODEVICE
2528 if (!*args[cur_arg + 1]) {
2529 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2530 file, linenum, args[0]);
2531 return -1;
2532 }
2533 if (curproxy->iface_name)
2534 free(curproxy->iface_name);
2535
2536 curproxy->iface_name = strdup(args[cur_arg + 1]);
2537 curproxy->iface_len = strlen(curproxy->iface_name);
2538 global.last_checks |= LSTCHK_NETADM;
2539#else
2540 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2541 file, linenum, args[0], args[cur_arg]);
2542 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002543#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002544 cur_arg += 2;
2545 continue;
2546 }
2547 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2548 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002549 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002552 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2553 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2554 file, linenum, "usesrc", "source");
2555 return -1;
2556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2558 regex_t *preg;
2559 if (curproxy == &defproxy) {
2560 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2561 return -1;
2562 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2564 return 0;
2565
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 if (*(args[1]) == 0 || *(args[2]) == 0) {
2567 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2568 file, linenum, args[0]);
2569 return -1;
2570 }
2571
2572 preg = calloc(1, sizeof(regex_t));
2573 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2574 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2575 return -1;
2576 }
2577
2578 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2579 if (err) {
2580 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2581 file, linenum, *err);
2582 return -1;
2583 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002584 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2587 regex_t *preg;
2588 if (curproxy == &defproxy) {
2589 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2590 return -1;
2591 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002592 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2593 return 0;
2594
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 if (*(args[1]) == 0) {
2596 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2597 return -1;
2598 }
2599
2600 preg = calloc(1, sizeof(regex_t));
2601 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2602 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2603 return -1;
2604 }
2605
2606 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002607 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2610 regex_t *preg;
2611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2613 return -1;
2614 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2616 return 0;
2617
Willy Tarreaubaaee002006-06-26 02:48:02 +02002618 if (*(args[1]) == 0) {
2619 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2620 return -1;
2621 }
2622
2623 preg = calloc(1, sizeof(regex_t));
2624 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2625 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2626 return -1;
2627 }
2628
2629 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002630 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 }
2632 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2633 regex_t *preg;
2634 if (curproxy == &defproxy) {
2635 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2636 return -1;
2637 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2639 return 0;
2640
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 if (*(args[1]) == 0) {
2642 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2643 return -1;
2644 }
2645
2646 preg = calloc(1, sizeof(regex_t));
2647 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2648 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2649 return -1;
2650 }
2651
2652 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002653 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002654 }
2655 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2656 regex_t *preg;
2657 if (curproxy == &defproxy) {
2658 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2659 return -1;
2660 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002661 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2662 return 0;
2663
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 if (*(args[1]) == 0) {
2665 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2666 return -1;
2667 }
2668
2669 preg = calloc(1, sizeof(regex_t));
2670 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2671 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2672 return -1;
2673 }
2674
2675 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002676 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002678 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2679 regex_t *preg;
2680 if (curproxy == &defproxy) {
2681 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2682 return -1;
2683 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002684 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2685 return 0;
2686
Willy Tarreaub8750a82006-09-03 09:56:00 +02002687 if (*(args[1]) == 0) {
2688 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2689 return -1;
2690 }
2691
2692 preg = calloc(1, sizeof(regex_t));
2693 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2694 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2695 return -1;
2696 }
2697
2698 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002699 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002700 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002701 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2702 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002704 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2705 return -1;
2706 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002707 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2708 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002709
Willy Tarreau977b8e42006-12-29 14:19:17 +01002710 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002711 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2712 file, linenum, args[0]);
2713 return -1;
2714 }
2715
2716 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002718 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2719 }
2720
2721 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002722 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002723 }
2724 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2725 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002727 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2728 return -1;
2729 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002730 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2731 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002732
Willy Tarreau977b8e42006-12-29 14:19:17 +01002733 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002734 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2735 file, linenum, args[0]);
2736 return -1;
2737 }
2738
2739 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002740 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002741 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2742 }
2743
2744 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002745 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2748 regex_t *preg;
2749 if (curproxy == &defproxy) {
2750 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2751 return -1;
2752 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002753 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2754 return 0;
2755
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 if (*(args[1]) == 0 || *(args[2]) == 0) {
2757 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2758 file, linenum, args[0]);
2759 return -1;
2760 }
2761
2762 preg = calloc(1, sizeof(regex_t));
2763 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2764 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2765 return -1;
2766 }
2767
2768 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2769 if (err) {
2770 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2771 file, linenum, *err);
2772 return -1;
2773 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002774 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
2776 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2777 regex_t *preg;
2778 if (curproxy == &defproxy) {
2779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2780 return -1;
2781 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2783 return 0;
2784
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 if (*(args[1]) == 0) {
2786 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2787 return -1;
2788 }
2789
2790 preg = calloc(1, sizeof(regex_t));
2791 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2792 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2793 return -1;
2794 }
2795
2796 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002797 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2800 regex_t *preg;
2801 if (curproxy == &defproxy) {
2802 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2803 return -1;
2804 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002805 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2806 return 0;
2807
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808 if (*(args[1]) == 0) {
2809 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2810 return -1;
2811 }
2812
2813 preg = calloc(1, sizeof(regex_t));
2814 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2815 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2816 return -1;
2817 }
2818
2819 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002820 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002821 }
2822 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2823 regex_t *preg;
2824 if (curproxy == &defproxy) {
2825 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2826 return -1;
2827 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2829 return 0;
2830
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 if (*(args[1]) == 0) {
2832 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2833 return -1;
2834 }
2835
2836 preg = calloc(1, sizeof(regex_t));
2837 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2838 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2839 return -1;
2840 }
2841
2842 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002843 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
2845 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2846 regex_t *preg;
2847 if (curproxy == &defproxy) {
2848 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2849 return -1;
2850 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2852 return 0;
2853
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 if (*(args[1]) == 0) {
2855 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2856 return -1;
2857 }
2858
2859 preg = calloc(1, sizeof(regex_t));
2860 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2861 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2862 return -1;
2863 }
2864
2865 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002866 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002868 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2869 regex_t *preg;
2870 if (curproxy == &defproxy) {
2871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2872 return -1;
2873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002874 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2875 return 0;
2876
Willy Tarreaub8750a82006-09-03 09:56:00 +02002877 if (*(args[1]) == 0) {
2878 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2879 return -1;
2880 }
2881
2882 preg = calloc(1, sizeof(regex_t));
2883 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2884 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2885 return -1;
2886 }
2887
2888 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002889 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2892 if (curproxy == &defproxy) {
2893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2894 return -1;
2895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002896 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2897 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898
2899 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2900 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2901 return 0;
2902 }
2903
2904 if (*(args[1]) == 0) {
2905 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2906 return -1;
2907 }
2908
2909 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002910 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
2912 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2913 regex_t *preg;
2914
2915 if (*(args[1]) == 0 || *(args[2]) == 0) {
2916 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2917 file, linenum, args[0]);
2918 return -1;
2919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002920 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2921 return 0;
2922
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 preg = calloc(1, sizeof(regex_t));
2924 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2925 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2926 return -1;
2927 }
2928
2929 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2930 if (err) {
2931 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2932 file, linenum, *err);
2933 return -1;
2934 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002935 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 }
2937 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2938 regex_t *preg;
2939 if (curproxy == &defproxy) {
2940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2941 return -1;
2942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002943 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2944 return 0;
2945
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2948 return -1;
2949 }
2950
2951 preg = calloc(1, sizeof(regex_t));
2952 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2953 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2954 return -1;
2955 }
2956
2957 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2958 if (err) {
2959 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2960 file, linenum, *err);
2961 return -1;
2962 }
2963 }
2964 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2965 regex_t *preg;
2966 if (curproxy == &defproxy) {
2967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2968 return -1;
2969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2971 return 0;
2972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2975 return -1;
2976 }
2977
2978 preg = calloc(1, sizeof(regex_t));
2979 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2980 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2981 return -1;
2982 }
2983
2984 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2985 if (err) {
2986 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2987 file, linenum, *err);
2988 return -1;
2989 }
2990 }
2991 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2992 regex_t *preg;
2993 if (curproxy == &defproxy) {
2994 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2995 return -1;
2996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002997 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2998 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999
3000 if (*(args[1]) == 0 || *(args[2]) == 0) {
3001 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3002 file, linenum, args[0]);
3003 return -1;
3004 }
3005
3006 preg = calloc(1, sizeof(regex_t));
3007 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3008 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3009 return -1;
3010 }
3011
3012 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3013 if (err) {
3014 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3015 file, linenum, *err);
3016 return -1;
3017 }
3018 }
3019 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3020 regex_t *preg;
3021 if (curproxy == &defproxy) {
3022 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3023 return -1;
3024 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3026 return 0;
3027
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 if (*(args[1]) == 0) {
3029 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
3030 return -1;
3031 }
3032
3033 preg = calloc(1, sizeof(regex_t));
3034 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3035 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3036 return -1;
3037 }
3038
3039 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3040 if (err) {
3041 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3042 file, linenum, *err);
3043 return -1;
3044 }
3045 }
3046 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3047 regex_t *preg;
3048 if (curproxy == &defproxy) {
3049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3050 return -1;
3051 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003052 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3053 return 0;
3054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 if (*(args[1]) == 0) {
3056 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
3057 return -1;
3058 }
3059
3060 preg = calloc(1, sizeof(regex_t));
3061 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3062 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
3063 return -1;
3064 }
3065
3066 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3067 if (err) {
3068 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3069 file, linenum, *err);
3070 return -1;
3071 }
3072 }
3073 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3074 if (curproxy == &defproxy) {
3075 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3076 return -1;
3077 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003078 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
3079 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080
3081 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3082 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
3083 return 0;
3084 }
3085
3086 if (*(args[1]) == 0) {
3087 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
3088 return -1;
3089 }
3090
3091 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3092 }
3093 else if (!strcmp(args[0], "errorloc") ||
3094 !strcmp(args[0], "errorloc302") ||
3095 !strcmp(args[0], "errorloc303")) { /* error location */
3096 int errnum, errlen;
3097 char *err;
3098
Willy Tarreau977b8e42006-12-29 14:19:17 +01003099 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3100 return 0;
3101
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003103 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 return -1;
3105 }
3106
3107 errnum = atol(args[1]);
3108 if (!strcmp(args[0], "errorloc303")) {
3109 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3110 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3111 } else {
3112 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3113 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3114 }
3115
Willy Tarreau0f772532006-12-23 20:51:41 +01003116 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3117 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003118 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003119 curproxy->errmsg[rc].str = err;
3120 curproxy->errmsg[rc].len = errlen;
3121 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003124
3125 if (rc >= HTTP_ERR_SIZE) {
3126 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3127 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 free(err);
3129 }
3130 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003131 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3132 int errnum, errlen, fd;
3133 char *err;
3134 struct stat stat;
3135
3136 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3137 return 0;
3138
3139 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003140 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003141 return -1;
3142 }
3143
3144 fd = open(args[2], O_RDONLY);
3145 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3146 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3147 file, linenum, args[2], args[1]);
3148 if (fd >= 0)
3149 close(fd);
3150 return -1;
3151 }
3152
3153 if (stat.st_size <= BUFSIZE) {
3154 errlen = stat.st_size;
3155 } else {
3156 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3157 file, linenum, args[2], BUFSIZE);
3158 errlen = BUFSIZE;
3159 }
3160
3161 err = malloc(errlen); /* malloc() must succeed during parsing */
3162 errnum = read(fd, err, errlen);
3163 if (errnum != errlen) {
3164 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3165 file, linenum, args[2], args[1]);
3166 close(fd);
3167 free(err);
3168 return -1;
3169 }
3170 close(fd);
3171
3172 errnum = atol(args[1]);
3173 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3174 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003175 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003176 curproxy->errmsg[rc].str = err;
3177 curproxy->errmsg[rc].len = errlen;
3178 break;
3179 }
3180 }
3181
3182 if (rc >= HTTP_ERR_SIZE) {
3183 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3184 file, linenum, errnum);
3185 free(err);
3186 }
3187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003189 struct cfg_kw_list *kwl;
3190 int index;
3191
3192 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3193 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3194 if (kwl->kw[index].section != CFG_LISTEN)
3195 continue;
3196 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3197 /* prepare error message just in case */
3198 snprintf(trash, sizeof(trash),
3199 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003200 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3201 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003202 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3203 return -1;
3204 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003205 else if (rc > 0) {
3206 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3207 return 0;
3208 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003209 return 0;
3210 }
3211 }
3212 }
3213
Willy Tarreau6daf3432008-01-22 16:44:08 +01003214 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 return -1;
3216 }
3217 return 0;
3218}
3219
3220
3221/*
3222 * This function reads and parses the configuration file given in the argument.
3223 * returns 0 if OK, -1 if error.
3224 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003225int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003227 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 FILE *f;
3229 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 int confsect = CFG_NONE;
3231
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 if ((f=fopen(file,"r")) == NULL)
3233 return -1;
3234
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003235 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003236 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003237 char *end;
3238 char *args[MAX_LINE_ARGS + 1];
3239 char *line = thisline;
3240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 linenum++;
3242
3243 end = line + strlen(line);
3244
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003245 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3246 /* Check if we reached the limit and the last char is not \n.
3247 * Watch out for the last line without the terminating '\n'!
3248 */
3249 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003250 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003251 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003252 }
3253
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003255 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 line++;
3257
3258 arg = 0;
3259 args[arg] = line;
3260
3261 while (*line && arg < MAX_LINE_ARGS) {
3262 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3263 * C equivalent value. Other combinations left unchanged (eg: \1).
3264 */
3265 if (*line == '\\') {
3266 int skip = 0;
3267 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3268 *line = line[1];
3269 skip = 1;
3270 }
3271 else if (line[1] == 'r') {
3272 *line = '\r';
3273 skip = 1;
3274 }
3275 else if (line[1] == 'n') {
3276 *line = '\n';
3277 skip = 1;
3278 }
3279 else if (line[1] == 't') {
3280 *line = '\t';
3281 skip = 1;
3282 }
3283 else if (line[1] == 'x') {
3284 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3285 unsigned char hex1, hex2;
3286 hex1 = toupper(line[2]) - '0';
3287 hex2 = toupper(line[3]) - '0';
3288 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3289 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3290 *line = (hex1<<4) + hex2;
3291 skip = 3;
3292 }
3293 else {
3294 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003295 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297 }
3298 if (skip) {
3299 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3300 end -= skip;
3301 }
3302 line++;
3303 }
3304 else if (*line == '#' || *line == '\n' || *line == '\r') {
3305 /* end of string, end of loop */
3306 *line = 0;
3307 break;
3308 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003309 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003311 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003312 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 line++;
3314 args[++arg] = line;
3315 }
3316 else {
3317 line++;
3318 }
3319 }
3320
3321 /* empty line */
3322 if (!**args)
3323 continue;
3324
Willy Tarreau540abe42007-05-02 20:50:16 +02003325 /* zero out remaining args and ensure that at least one entry
3326 * is zeroed out.
3327 */
3328 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 args[arg] = line;
3330 }
3331
Willy Tarreau3842f002009-06-14 11:39:52 +02003332 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003333 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003334 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003335 for (arg=0; *args[arg+1]; arg++)
3336 args[arg] = args[arg+1]; // shift args after inversion
3337 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003338 else if (!strcmp(args[0], "default")) {
3339 kwm = KWM_DEF;
3340 for (arg=0; *args[arg+1]; arg++)
3341 args[arg] = args[arg+1]; // shift args after inversion
3342 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003343
Willy Tarreau3842f002009-06-14 11:39:52 +02003344 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3345 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003346 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003347 }
3348
Willy Tarreau977b8e42006-12-29 14:19:17 +01003349 if (!strcmp(args[0], "listen") ||
3350 !strcmp(args[0], "frontend") ||
3351 !strcmp(args[0], "backend") ||
3352 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003353 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003355 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003356 cursection = strdup(args[0]);
3357 }
3358 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003360 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003361 cursection = strdup(args[0]);
3362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 /* else it's a section keyword */
3364
3365 switch (confsect) {
3366 case CFG_LISTEN:
Willy Tarreau3842f002009-06-14 11:39:52 +02003367 if (cfg_parse_listen(file, linenum, args, kwm) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003368 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 break;
3370 case CFG_GLOBAL:
Willy Tarreau3842f002009-06-14 11:39:52 +02003371 if (cfg_parse_global(file, linenum, args, kwm) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003372 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 break;
3374 default:
3375 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003376 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003379 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003380 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 fclose(f);
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003382 return 0;
3383 err:
3384 free(cursection);
3385 cursection = NULL;
3386 return -1;
3387}
3388
3389int check_config_validity()
3390{
3391 int cfgerr = 0;
3392 struct proxy *curproxy = NULL;
3393 struct server *newsrv = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394
3395 /*
3396 * Now, check for the integrity of all that we have collected.
3397 */
3398
3399 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003400 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003402 /* first, we will invert the proxy list order */
3403 curproxy = NULL;
3404 while (proxy) {
3405 struct proxy *next;
3406
3407 next = proxy->next;
3408 proxy->next = curproxy;
3409 curproxy = proxy;
3410 if (!next)
3411 break;
3412 proxy = next;
3413 }
3414
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003416 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003417 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419
3420 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003421 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003422 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003423
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003425 /* ensure we don't keep listeners uselessly bound */
3426 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 curproxy = curproxy->next;
3428 continue;
3429 }
3430
Willy Tarreauff01a212009-03-15 13:46:16 +01003431 switch (curproxy->mode) {
3432 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003433 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003434 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003435 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3436 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003437 cfgerr++;
3438 }
3439
3440 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003441 Warning("config : servers will be ignored for %s '%s'.\n",
3442 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003443 break;
3444
3445 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003446 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003447 break;
3448
3449 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003450 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003451 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003452 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3453 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003454 cfgerr++;
3455 }
3456 break;
3457 }
3458
3459 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003460 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3461 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 cfgerr++;
3463 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003464
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003465 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3466 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3467 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003468 Alert("config : %s '%s' cannot use both transparent and 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#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003473 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003474 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3475 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003476 cfgerr++;
3477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003479 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003480 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3481 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003482 }
3483 }
3484 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3485 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3486 /* If no LB algo is set in a backend, and we're not in
3487 * transparent mode, dispatch mode nor proxy mode, we
3488 * want to use balance roundrobin by default.
3489 */
3490 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3491 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 }
3493 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003494
Willy Tarreau82936582007-11-30 15:20:09 +01003495 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3496 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003497 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3498 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreau82936582007-11-30 15:20:09 +01003499 }
3500
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003501 /* if a default backend was specified, let's find it */
3502 if (curproxy->defbe.name) {
3503 struct proxy *target;
3504
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003505 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3506 if (!target) {
3507 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3508 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003509 cfgerr++;
3510 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003511 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3512 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003513 } else {
3514 free(curproxy->defbe.name);
3515 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003516 /* we force the backend to be present on at least all of
3517 * the frontend's processes.
3518 */
3519 target->bind_proc = curproxy->bind_proc ?
3520 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
3522 }
3523
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003524 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003525 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3526 /* map jump target for ACT_SETBE in req_rep chain */
3527 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003528 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003529 struct proxy *target;
3530
Willy Tarreaua496b602006-12-17 23:15:24 +01003531 if (exp->action != ACT_SETBE)
3532 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003533
3534 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3535 if (!target) {
3536 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3537 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003538 cfgerr++;
3539 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003540 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3541 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003542 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003543 } else {
3544 free((void *)exp->replace);
3545 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003546 /* we force the backend to be present on at least all of
3547 * the frontend's processes.
3548 */
3549 target->bind_proc = curproxy->bind_proc ?
3550 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003551 }
3552 }
3553 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003554
3555 /* find the target proxy for 'use_backend' rules */
3556 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003557 struct proxy *target;
3558
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003559 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003560
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003561 if (!target) {
3562 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3563 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003564 cfgerr++;
3565 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003566 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3567 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003568 cfgerr++;
3569 } else {
3570 free((void *)rule->be.name);
3571 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003572 /* we force the backend to be present on at least all of
3573 * the frontend's processes.
3574 */
3575 target->bind_proc = curproxy->bind_proc ?
3576 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003577 }
3578 }
3579
Willy Tarreau2738a142006-07-08 17:28:09 +02003580 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003581 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003582 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003583 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003584 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003585 " | While not properly invalid, you will certainly encounter various problems\n"
3586 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003587 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003589 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003590
Willy Tarreau1fa31262007-12-03 00:36:16 +01003591 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3592 * We must still support older configurations, so let's find out whether those
3593 * parameters have been set or must be copied from contimeouts.
3594 */
3595 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003596 if (!curproxy->timeout.tarpit ||
3597 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003598 /* tarpit timeout not set. We search in the following order:
3599 * default.tarpit, curr.connect, default.connect.
3600 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003601 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003602 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003603 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003604 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003605 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003606 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003607 }
3608 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003609 (!curproxy->timeout.queue ||
3610 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003611 /* queue timeout not set. We search in the following order:
3612 * default.queue, curr.connect, default.connect.
3613 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003614 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003615 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003616 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003617 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003618 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003619 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003620 }
3621 }
3622
Willy Tarreauf3c69202006-07-09 16:42:34 +02003623 if (curproxy->options & PR_O_SSL3_CHK) {
3624 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3625 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3626 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3627 }
3628
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003629 /* The small pools required for the capture lists */
3630 if (curproxy->nb_req_cap)
3631 curproxy->req_cap_pool = create_pool("ptrcap",
3632 curproxy->nb_req_cap * sizeof(char *),
3633 MEM_F_SHARED);
3634 if (curproxy->nb_rsp_cap)
3635 curproxy->rsp_cap_pool = create_pool("ptrcap",
3636 curproxy->nb_rsp_cap * sizeof(char *),
3637 MEM_F_SHARED);
3638
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003639 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3640 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3641 MEM_F_SHARED);
3642
Willy Tarreau86034312006-12-29 00:10:33 +01003643 /* for backwards compatibility with "listen" instances, if
3644 * fullconn is not set but maxconn is set, then maxconn
3645 * is used.
3646 */
3647 if (!curproxy->fullconn)
3648 curproxy->fullconn = curproxy->maxconn;
3649
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 /* first, we will invert the servers list order */
3651 newsrv = NULL;
3652 while (curproxy->srv) {
3653 struct server *next;
3654
3655 next = curproxy->srv->next;
3656 curproxy->srv->next = newsrv;
3657 newsrv = curproxy->srv;
3658 if (!next)
3659 break;
3660 curproxy->srv = next;
3661 }
3662
Willy Tarreau20697042007-11-15 23:26:18 +01003663 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003664 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665
Willy Tarreaub625a082007-11-26 01:15:43 +01003666 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003667 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003668 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003669 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3670 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003671 else
3672 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673
3674 if (curproxy->options & PR_O_LOGASAP)
3675 curproxy->to_log &= ~LW_BYTES;
3676
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003678 * ensure that we're not cross-dressing a TCP server into HTTP.
3679 */
3680 newsrv = curproxy->srv;
3681 while (newsrv != NULL) {
3682 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003683 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3684 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003685 goto err;
3686 }
3687 newsrv = newsrv->next;
3688 }
3689
3690 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 * If this server supports a maxconn parameter, it needs a dedicated
3692 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003693 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 */
3695 newsrv = curproxy->srv;
3696 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003697 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 /* Only 'minconn' was specified, or it was higher than or equal
3699 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3700 * this will avoid further useless expensive computations.
3701 */
3702 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003703 } else if (newsrv->maxconn && !newsrv->minconn) {
3704 /* minconn was not specified, so we set it to maxconn */
3705 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003706 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003707 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3708 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003709 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 }
3711
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003712 if (newsrv->trackit) {
3713 struct proxy *px;
3714 struct server *srv;
3715 char *pname, *sname;
3716
3717 pname = newsrv->trackit;
3718 sname = strrchr(pname, '/');
3719
3720 if (sname)
3721 *sname++ = '\0';
3722 else {
3723 sname = pname;
3724 pname = NULL;
3725 }
3726
3727 if (pname) {
3728 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3729 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003730 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3731 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003732 newsrv->id, pname);
3733 return -1;
3734 }
3735 } else
3736 px = curproxy;
3737
3738 srv = findserver(px, sname);
3739 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003740 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3741 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003742 newsrv->id, sname);
3743 return -1;
3744 }
3745
3746 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003747 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003748 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003749 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003750 newsrv->id, px->id, srv->id);
3751 return -1;
3752 }
3753
3754 if (curproxy != px &&
3755 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003756 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003757 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003758 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003759 newsrv->id, px->id, srv->id);
3760 return -1;
3761 }
3762
3763 newsrv->tracked = srv;
3764 newsrv->tracknext = srv->tracknext;
3765 srv->tracknext = newsrv;
3766
3767 free(newsrv->trackit);
3768 }
3769
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 newsrv = newsrv->next;
3771 }
3772
Willy Tarreaue6b98942007-10-29 01:09:36 +01003773 /* adjust this proxy's listeners */
3774 listener = curproxy->listen;
3775 while (listener) {
3776 if (curproxy->options & PR_O_TCP_NOLING)
3777 listener->options |= LI_O_NOLINGER;
3778 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003779 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003780 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003781 listener->accept = event_accept;
3782 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003783 listener->handler = process_session;
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02003784 /* both TCP and HTTP must check switching rules */
3785 listener->analysers |= AN_REQ_SWITCHING_RULES;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003786
3787 if (curproxy->mode == PR_MODE_HTTP)
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02003788 listener->analysers |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003789
Willy Tarreau9ea05a72009-06-14 12:07:01 +02003790 /* smart accept mode is automatic in HTTP mode */
3791 if ((curproxy->options2 & PR_O2_SMARTACC) ||
3792 (curproxy->mode == PR_MODE_HTTP &&
3793 !(curproxy->no_options2 & PR_O2_SMARTACC)))
3794 listener->options |= LI_O_NOQUICKACK;
3795
Willy Tarreaud869b242009-03-15 14:43:58 +01003796 if (curproxy->tcp_req.inspect_delay ||
3797 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003798 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003799
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02003800 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01003801 listener = listener->next;
3802 }
3803
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 curproxy = curproxy->next;
3805 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003806
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 if (cfgerr > 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003808 Alert("Errors found in configuration, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003809 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003811
3812 /*
3813 * Recount currently required checks.
3814 */
3815
3816 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3817 int optnum;
3818
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003819 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3820 if (curproxy->options & cfg_opts[optnum].val)
3821 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003822
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003823 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3824 if (curproxy->options2 & cfg_opts2[optnum].val)
3825 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003826 }
3827
3828 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003829 err:
Willy Tarreau6daf3432008-01-22 16:44:08 +01003830 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831}
3832
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003833/*
3834 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3835 * parsing sessions.
3836 */
3837void cfg_register_keywords(struct cfg_kw_list *kwl)
3838{
3839 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3840}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003842/*
3843 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3844 */
3845void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3846{
3847 LIST_DEL(&kwl->list);
3848 LIST_INIT(&kwl->list);
3849}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850
3851/*
3852 * Local variables:
3853 * c-indent-level: 8
3854 * c-basic-offset: 8
3855 * End:
3856 */