blob: 3a71df2506db5d41fe660b30c07a32d6ceb06046 [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 Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200126 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
127 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200128 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
129 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100130 { NULL, 0, 0, 0 }
131};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132
Willy Tarreau6daf3432008-01-22 16:44:08 +0100133static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200134static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
135int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100136int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200137
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200138/* List head of all known configuration keywords */
139static struct cfg_kw_list cfg_keywords = {
140 .list = LIST_HEAD_INIT(cfg_keywords.list)
141};
142
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143/*
144 * converts <str> to a list of listeners which are dynamically allocated.
145 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
146 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
147 * - <port> is a numerical port from 1 to 65535 ;
148 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
149 * This can be repeated as many times as necessary, separated by a coma.
150 * The <tail> argument is a pointer to a current list which should be appended
151 * to the tail of the new list. The pointer to the new list is returned.
152 */
153static struct listener *str2listener(char *str, struct listener *tail)
154{
155 struct listener *l;
156 char *c, *next, *range, *dupstr;
157 int port, end;
158
159 next = dupstr = strdup(str);
160
161 while (next && *next) {
162 struct sockaddr_storage ss;
163
164 str = next;
165 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100166 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167 *next++ = 0;
168 }
169
170 /* 2) look for the addr/port delimiter, it's the last colon. */
171 if ((range = strrchr(str, ':')) == NULL) {
172 Alert("Missing port number: '%s'\n", str);
173 goto fail;
174 }
175
176 *range++ = 0;
177
178 if (strrchr(str, ':') != NULL) {
179 /* IPv6 address contains ':' */
180 memset(&ss, 0, sizeof(ss));
181 ss.ss_family = AF_INET6;
182
183 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
184 Alert("Invalid server address: '%s'\n", str);
185 goto fail;
186 }
187 }
188 else {
189 memset(&ss, 0, sizeof(ss));
190 ss.ss_family = AF_INET;
191
192 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
193 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
194 }
195 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
196 struct hostent *he;
197
198 if ((he = gethostbyname(str)) == NULL) {
199 Alert("Invalid server name: '%s'\n", str);
200 goto fail;
201 }
202 else
203 ((struct sockaddr_in *)&ss)->sin_addr =
204 *(struct in_addr *) *(he->h_addr_list);
205 }
206 }
207
208 /* 3) look for the port-end delimiter */
209 if ((c = strchr(range, '-')) != NULL) {
210 *c++ = 0;
211 end = atol(c);
212 }
213 else {
214 end = atol(range);
215 }
216
217 port = atol(range);
218
219 if (port < 1 || port > 65535) {
220 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
221 goto fail;
222 }
223
224 if (end < 1 || end > 65535) {
225 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
226 goto fail;
227 }
228
229 for (; port <= end; port++) {
230 l = (struct listener *)calloc(1, sizeof(struct listener));
231 l->next = tail;
232 tail = l;
233
234 l->fd = -1;
235 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 l->state = LI_INIT;
237
238 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100240 tcpv6_add_listener(l);
241 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100243 tcpv4_add_listener(l);
244 }
245 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246 } /* end for(port) */
247 } /* end while(next) */
248 free(dupstr);
249 return tail;
250 fail:
251 free(dupstr);
252 return NULL;
253}
254
Willy Tarreau977b8e42006-12-29 14:19:17 +0100255/*
256 * Sends a warning if proxy <proxy> does not have at least one of the
257 * capabilities in <cap>. An optionnal <hint> may be added at the end
258 * of the warning to help the user. Returns 1 if a warning was emitted
259 * or 0 if the condition is valid.
260 */
261int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
262{
263 char *msg;
264
265 switch (cap) {
266 case PR_CAP_BE: msg = "no backend"; break;
267 case PR_CAP_FE: msg = "no frontend"; break;
268 case PR_CAP_RS: msg = "no ruleset"; break;
269 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
270 default: msg = "not enough"; break;
271 }
272
273 if (!(proxy->cap & cap)) {
274 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100275 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100276 return 1;
277 }
278 return 0;
279}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
Willy Tarreau61d18892009-03-31 10:49:21 +0200281/* Report a warning if a rule is placed after a 'block' rule.
282 * Return 1 if the warning has been emitted, otherwise 0.
283 */
284int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
285{
286 if (!LIST_ISEMPTY(&proxy->block_cond)) {
287 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
288 file, line, arg);
289 return 1;
290 }
291 return 0;
292}
293
294/* Report a warning if a rule is placed after a reqrewrite rule.
295 * Return 1 if the warning has been emitted, otherwise 0.
296 */
297int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
298{
299 if (proxy->req_exp) {
300 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
301 file, line, arg);
302 return 1;
303 }
304 return 0;
305}
306
307/* Report a warning if a rule is placed after a reqadd rule.
308 * Return 1 if the warning has been emitted, otherwise 0.
309 */
310int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
311{
312 if (proxy->nb_reqadd) {
313 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
314 file, line, arg);
315 return 1;
316 }
317 return 0;
318}
319
320/* Report a warning if a rule is placed after a redirect rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
324{
325 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a 'use_backend' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
336int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
337{
338 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* report a warning if a block rule is dangerously placed */
347int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
348{
349 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
350 warnif_rule_after_reqadd(proxy, file, line, arg) ||
351 warnif_rule_after_redirect(proxy, file, line, arg) ||
352 warnif_rule_after_use_backend(proxy, file, line, arg);
353}
354
355/* report a warning if a reqxxx rule is dangerously placed */
356int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
357{
358 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
359 warnif_rule_after_redirect(proxy, file, line, arg) ||
360 warnif_rule_after_use_backend(proxy, file, line, arg);
361}
362
363/* report a warning if a reqadd rule is dangerously placed */
364int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
365{
366 return warnif_rule_after_redirect(proxy, file, line, arg) ||
367 warnif_rule_after_use_backend(proxy, file, line, arg);
368}
369
Willy Tarreaubaaee002006-06-26 02:48:02 +0200370/*
371 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
372 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100373int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200374{
375
376 if (!strcmp(args[0], "global")) { /* new section */
377 /* no option, nothing special to do */
378 return 0;
379 }
380 else if (!strcmp(args[0], "daemon")) {
381 global.mode |= MODE_DAEMON;
382 }
383 else if (!strcmp(args[0], "debug")) {
384 global.mode |= MODE_DEBUG;
385 }
386 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100387 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200388 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200389 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100390 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200391 }
392 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100393 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100396 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100398 else if (!strcmp(args[0], "nosplice")) {
399 global.tune.options &= ~GTUNE_USE_SPLICE;
400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401 else if (!strcmp(args[0], "quiet")) {
402 global.mode |= MODE_QUIET;
403 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200404 else if (!strcmp(args[0], "tune.maxpollevents")) {
405 if (global.tune.maxpollevents != 0) {
406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
407 return 0;
408 }
409 if (*(args[1]) == 0) {
410 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
411 return -1;
412 }
413 global.tune.maxpollevents = atol(args[1]);
414 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100415 else if (!strcmp(args[0], "tune.maxaccept")) {
416 if (global.tune.maxaccept != 0) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.tune.maxaccept = atol(args[1]);
425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 else if (!strcmp(args[0], "uid")) {
427 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200428 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 return 0;
430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
433 return -1;
434 }
435 global.uid = atol(args[1]);
436 }
437 else if (!strcmp(args[0], "gid")) {
438 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200439 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440 return 0;
441 }
442 if (*(args[1]) == 0) {
443 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
444 return -1;
445 }
446 global.gid = atol(args[1]);
447 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200448 /* user/group name handling */
449 else if (!strcmp(args[0], "user")) {
450 struct passwd *ha_user;
451 if (global.uid != 0) {
452 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
453 return 0;
454 }
455 errno = 0;
456 ha_user = getpwnam(args[1]);
457 if (ha_user != NULL) {
458 global.uid = (int)ha_user->pw_uid;
459 }
460 else {
461 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
462 exit(1);
463 }
464 }
465 else if (!strcmp(args[0], "group")) {
466 struct group *ha_group;
467 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200468 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200469 return 0;
470 }
471 errno = 0;
472 ha_group = getgrnam(args[1]);
473 if (ha_group != NULL) {
474 global.gid = (int)ha_group->gr_gid;
475 }
476 else {
477 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
478 exit(1);
479 }
480 }
481 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "nbproc")) {
483 if (global.nbproc != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
485 return 0;
486 }
487 if (*(args[1]) == 0) {
488 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
489 return -1;
490 }
491 global.nbproc = atol(args[1]);
492 }
493 else if (!strcmp(args[0], "maxconn")) {
494 if (global.maxconn != 0) {
495 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
496 return 0;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
500 return -1;
501 }
502 global.maxconn = atol(args[1]);
503#ifdef SYSTEM_MAXCONN
504 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
505 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);
506 global.maxconn = DEFAULT_MAXCONN;
507 }
508#endif /* SYSTEM_MAXCONN */
509 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100510 else if (!strcmp(args[0], "maxpipes")) {
511 if (global.maxpipes != 0) {
512 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
513 return 0;
514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
517 return -1;
518 }
519 global.maxpipes = atol(args[1]);
520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "ulimit-n")) {
522 if (global.rlimit_nofile != 0) {
523 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
524 return 0;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
528 return -1;
529 }
530 global.rlimit_nofile = atol(args[1]);
531 }
532 else if (!strcmp(args[0], "chroot")) {
533 if (global.chroot != NULL) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
535 return 0;
536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
539 return -1;
540 }
541 global.chroot = strdup(args[1]);
542 }
543 else if (!strcmp(args[0], "pidfile")) {
544 if (global.pidfile != NULL) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
546 return 0;
547 }
548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
550 return -1;
551 }
552 global.pidfile = strdup(args[1]);
553 }
554 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100555 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 int facility, level;
557
558 if (*(args[1]) == 0 || *(args[2]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
560 return -1;
561 }
562
563 facility = get_log_facility(args[2]);
564 if (facility < 0) {
565 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
566 exit(1);
567 }
568
569 level = 7; /* max syslog level = debug */
570 if (*(args[3])) {
571 level = get_log_level(args[3]);
572 if (level < 0) {
573 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
574 exit(1);
575 }
576 }
577
Robert Tsai81ae1952007-12-05 10:47:29 +0100578 if (args[1][0] == '/') {
579 logsrv.u.addr.sa_family = AF_UNIX;
580 logsrv.u.un = *str2sun(args[1]);
581 } else {
582 logsrv.u.addr.sa_family = AF_INET;
583 logsrv.u.in = *str2sa(args[1]);
584 if (!logsrv.u.in.sin_port)
585 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587
588 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100589 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 global.logfac1 = facility;
591 global.loglev1 = level;
592 }
593 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100594 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 global.logfac2 = facility;
596 global.loglev2 = level;
597 }
598 else {
599 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
600 return -1;
601 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200602 }
603 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
604 if (global.spread_checks != 0) {
605 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
606 return 0;
607 }
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
610 return -1;
611 }
612 global.spread_checks = atol(args[1]);
613 if (global.spread_checks < 0 || global.spread_checks > 50) {
614 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
615 return -1;
616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200619 struct cfg_kw_list *kwl;
620 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200621 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200622
623 list_for_each_entry(kwl, &cfg_keywords.list, list) {
624 for (index = 0; kwl->kw[index].kw != NULL; index++) {
625 if (kwl->kw[index].section != CFG_GLOBAL)
626 continue;
627 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
628 /* prepare error message just in case */
629 snprintf(trash, sizeof(trash),
630 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200631 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
632 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200633 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
634 return -1;
635 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200636 else if (rc > 0) {
637 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
638 return 0;
639 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200640 return 0;
641 }
642 }
643 }
644
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
646 return -1;
647 }
648 return 0;
649}
650
651
652static void init_default_instance()
653{
654 memset(&defproxy, 0, sizeof(defproxy));
655 defproxy.mode = PR_MODE_TCP;
656 defproxy.state = PR_STNEW;
657 defproxy.maxconn = cfg_maxpconn;
658 defproxy.conn_retries = CONN_RETRIES;
659 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200660
661 LIST_INIT(&defproxy.pendconns);
662 LIST_INIT(&defproxy.acl);
663 LIST_INIT(&defproxy.block_cond);
664 LIST_INIT(&defproxy.mon_fail_cond);
665 LIST_INIT(&defproxy.switching_rules);
666
Willy Tarreau3a70f942008-02-15 11:15:34 +0100667 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668}
669
670/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100671 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
672 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100674int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675{
676 static struct proxy *curproxy = NULL;
677 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200678 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100679 int rc;
680 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681
Willy Tarreau977b8e42006-12-29 14:19:17 +0100682 if (!strcmp(args[0], "listen"))
683 rc = PR_CAP_LISTEN;
684 else if (!strcmp(args[0], "frontend"))
685 rc = PR_CAP_FE | PR_CAP_RS;
686 else if (!strcmp(args[0], "backend"))
687 rc = PR_CAP_BE | PR_CAP_RS;
688 else if (!strcmp(args[0], "ruleset"))
689 rc = PR_CAP_RS;
690 else
691 rc = PR_CAP_NONE;
692
693 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 if (!*args[1]) {
695 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
696 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
697 file, linenum, args[0]);
698 return -1;
699 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200700
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100701 err = invalid_char(args[1]);
702 if (err) {
703 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
704 file, linenum, *err, args[0], args[1]);
705 return -1;
706 }
707
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200708 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
709 /*
710 * If there are two proxies with the same name only following
711 * combinations are allowed:
712 *
713 * listen backend frontend ruleset
714 * listen - - - -
715 * backend - - OK -
716 * frontend - OK - -
717 * ruleset - - - -
718 */
719
720 if (!strcmp(curproxy->id, args[1]) &&
721 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
722 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100723 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
724 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200725 }
726 }
727
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
729 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
730 return -1;
731 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100732
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 curproxy->next = proxy;
734 proxy = curproxy;
735 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200736 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200737 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200738 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100739 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200740 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200741 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742
Willy Tarreauee991362007-05-14 14:37:50 +0200743 /* Timeouts are defined as -1, so we cannot use the zeroed area
744 * as a default value.
745 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100746 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200747
748 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100750 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751
752 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100753 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 curproxy->listen = str2listener(args[2], curproxy->listen);
755 if (!curproxy->listen)
756 return -1;
757 global.maxsock++;
758 }
759
760 /* set default values */
761 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100763 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100764 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100765 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200766 curproxy->except_net = defproxy.except_net;
767 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200768 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200769 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200771 if (defproxy.fwdfor_hdr_len) {
772 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
773 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
774 }
775
Willy Tarreau977b8e42006-12-29 14:19:17 +0100776 if (curproxy->cap & PR_CAP_FE) {
777 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100778 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100779 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100780
781 /* initialize error relocations */
782 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
783 if (defproxy.errmsg[rc].str)
784 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
785 }
786
787 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (curproxy->cap & PR_CAP_BE) {
791 curproxy->fullconn = defproxy.fullconn;
792 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793
Willy Tarreau977b8e42006-12-29 14:19:17 +0100794 if (defproxy.check_req)
795 curproxy->check_req = strdup(defproxy.check_req);
796 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (defproxy.cookie_name)
799 curproxy->cookie_name = strdup(defproxy.cookie_name);
800 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100801
802 if (defproxy.url_param_name)
803 curproxy->url_param_name = strdup(defproxy.url_param_name);
804 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100805
Benoitaffb4812009-03-25 13:02:10 +0100806 if (defproxy.hh_name)
807 curproxy->hh_name = strdup(defproxy.hh_name);
808 curproxy->hh_len = defproxy.hh_len;
809 curproxy->hh_match_domain = defproxy.hh_match_domain;
810
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100811 if (defproxy.iface_name)
812 curproxy->iface_name = strdup(defproxy.iface_name);
813 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815
Willy Tarreau977b8e42006-12-29 14:19:17 +0100816 if (curproxy->cap & PR_CAP_RS) {
817 if (defproxy.capture_name)
818 curproxy->capture_name = strdup(defproxy.capture_name);
819 curproxy->capture_namelen = defproxy.capture_namelen;
820 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100824 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100825 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100826 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100827 curproxy->uri_auth = defproxy.uri_auth;
828 curproxy->mon_net = defproxy.mon_net;
829 curproxy->mon_mask = defproxy.mon_mask;
830 if (defproxy.monitor_uri)
831 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
832 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100833 if (defproxy.defbe.name)
834 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100835 }
836
837 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100838 curproxy->timeout.connect = defproxy.timeout.connect;
839 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100840 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100841 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100842 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100843 curproxy->source_addr = defproxy.source_addr;
844 }
845
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 curproxy->mode = defproxy.mode;
847 curproxy->logfac1 = defproxy.logfac1;
848 curproxy->logsrv1 = defproxy.logsrv1;
849 curproxy->loglev1 = defproxy.loglev1;
850 curproxy->logfac2 = defproxy.logfac2;
851 curproxy->logsrv2 = defproxy.logsrv2;
852 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200853 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100854 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
855 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200856
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 return 0;
858 }
859 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
860 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100861 /* FIXME-20070101: we should do this too at the end of the
862 * config parsing to free all default values.
863 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200864 free(defproxy.check_req);
865 free(defproxy.cookie_name);
866 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100867 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200868 free(defproxy.capture_name);
869 free(defproxy.monitor_uri);
870 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100871 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200872 free(defproxy.fwdfor_hdr_name);
873 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100874
Willy Tarreaua534fea2008-08-03 12:19:50 +0200875 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
876 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100877
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 /* we cannot free uri_auth because it might already be used */
879 init_default_instance();
880 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100881 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 return 0;
883 }
884 else if (curproxy == NULL) {
885 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
886 return -1;
887 }
888
Willy Tarreau977b8e42006-12-29 14:19:17 +0100889
890 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100892 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100893 int cur_arg;
894
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 if (curproxy == &defproxy) {
896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
897 return -1;
898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
900 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901
902 if (strchr(args[1], ':') == NULL) {
903 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
904 file, linenum, args[0]);
905 return -1;
906 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100907
908 last_listen = curproxy->listen;
909 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 if (!curproxy->listen)
911 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100912
913 cur_arg = 2;
914 while (*(args[cur_arg])) {
915 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
916#ifdef SO_BINDTODEVICE
917 struct listener *l;
918
919 if (!*args[cur_arg + 1]) {
920 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
921 file, linenum, args[0]);
922 return -1;
923 }
924
925 for (l = curproxy->listen; l != last_listen; l = l->next)
926 l->interface = strdup(args[cur_arg + 1]);
927
928 global.last_checks |= LSTCHK_NETADM;
929
930 cur_arg += 2;
931 continue;
932#else
933 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
934 file, linenum, args[0], args[cur_arg]);
935 return -1;
936#endif
937 }
938 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100939#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100940 struct listener *l;
941
942 for (l = curproxy->listen; l != last_listen; l = l->next)
943 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100944
945 cur_arg ++;
946 continue;
947#else
948 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
949 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100950 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100951#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100952 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100953 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100954 file, linenum, args[0]);
955 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 global.maxsock++;
958 return 0;
959 }
960 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
961 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
962 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
963 file, linenum, args[0]);
964 return -1;
965 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100966 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
967 return 0;
968
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 /* flush useless bits */
970 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
971 return 0;
972 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200973 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100974 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
975 return 0;
976
Willy Tarreau1c47f852006-07-09 08:22:27 +0200977 if (!*args[1]) {
978 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
979 file, linenum, args[0]);
980 return -1;
981 }
982
Willy Tarreaua534fea2008-08-03 12:19:50 +0200983 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100984 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200985 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100986 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200987 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
988
989 return 0;
990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
992 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
993 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
994 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
995 else {
996 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
997 return -1;
998 }
999 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001000 else if (!strcmp(args[0], "id")) {
1001 struct proxy *target;
1002
1003 if (curproxy == &defproxy) {
1004 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1005 file, linenum, args[0]);
1006 return -1;
1007 }
1008
1009 if (!*args[1]) {
1010 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1011 file, linenum, args[0]);
1012 return -1;
1013 }
1014
1015 curproxy->uuid = atol(args[1]);
1016
1017 if (curproxy->uuid < 1001) {
1018 Alert("parsing [%s:%d]: custom id has to be > 1000",
1019 file, linenum);
1020 return -1;
1021 }
1022
1023 for (target = proxy; target; target = target->next)
1024 if (curproxy != target && curproxy->uuid == target->uuid) {
1025 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1026 file, linenum, curproxy->id, target->id);
1027 return -1;
1028 }
1029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1031 curproxy->state = PR_STSTOPPED;
1032 }
1033 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1034 curproxy->state = PR_STNEW;
1035 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001036 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1037 int cur_arg = 1;
1038 unsigned int set = 0;
1039
1040 while (*args[cur_arg]) {
1041 int u;
1042 if (strcmp(args[cur_arg], "all") == 0) {
1043 set = 0;
1044 break;
1045 }
1046 else if (strcmp(args[cur_arg], "odd") == 0) {
1047 set |= 0x55555555;
1048 }
1049 else if (strcmp(args[cur_arg], "even") == 0) {
1050 set |= 0xAAAAAAAA;
1051 }
1052 else {
1053 u = str2uic(args[cur_arg]);
1054 if (u < 1 || u > 32) {
1055 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1056 file, linenum, args[0]);
1057 return -1;
1058 }
1059 if (u > global.nbproc) {
1060 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1061 file, linenum, args[0]);
1062 }
1063 set |= 1 << (u - 1);
1064 }
1065 cur_arg++;
1066 }
1067 curproxy->bind_proc = set;
1068 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001069 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001070 if (curproxy == &defproxy) {
1071 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1072 return -1;
1073 }
1074
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001075 err = invalid_char(args[1]);
1076 if (err) {
1077 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1078 file, linenum, *err, args[1]);
1079 return -1;
1080 }
1081
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001082 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1083 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1084 file, linenum, args[1]);
1085 return -1;
1086 }
1087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1089 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090
Willy Tarreau977b8e42006-12-29 14:19:17 +01001091 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1092 return 0;
1093
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 if (*(args[1]) == 0) {
1095 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1096 file, linenum, args[0]);
1097 return -1;
1098 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001099
1100 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 curproxy->cookie_name = strdup(args[1]);
1102 curproxy->cookie_len = strlen(curproxy->cookie_name);
1103
1104 cur_arg = 2;
1105 while (*(args[cur_arg])) {
1106 if (!strcmp(args[cur_arg], "rewrite")) {
1107 curproxy->options |= PR_O_COOK_RW;
1108 }
1109 else if (!strcmp(args[cur_arg], "indirect")) {
1110 curproxy->options |= PR_O_COOK_IND;
1111 }
1112 else if (!strcmp(args[cur_arg], "insert")) {
1113 curproxy->options |= PR_O_COOK_INS;
1114 }
1115 else if (!strcmp(args[cur_arg], "nocache")) {
1116 curproxy->options |= PR_O_COOK_NOC;
1117 }
1118 else if (!strcmp(args[cur_arg], "postonly")) {
1119 curproxy->options |= PR_O_COOK_POST;
1120 }
1121 else if (!strcmp(args[cur_arg], "prefix")) {
1122 curproxy->options |= PR_O_COOK_PFX;
1123 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001124 else if (!strcmp(args[cur_arg], "domain")) {
1125 if (!*args[cur_arg + 1]) {
1126 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1127 file, linenum, args[cur_arg]);
1128 return -1;
1129 }
1130
1131 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1132 /* rfc2109, 4.3.2 Rejecting Cookies */
1133 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1134 " dots or does not start with a dot.\n",
1135 file, linenum, args[cur_arg + 1]);
1136 return -1;
1137 }
1138
1139 err = invalid_domainchar(args[cur_arg + 1]);
1140 if (err) {
1141 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1142 file, linenum, *err, args[cur_arg + 1]);
1143 return -1;
1144 }
1145
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001146 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001147 cur_arg++;
1148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001150 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 file, linenum, args[0]);
1152 return -1;
1153 }
1154 cur_arg++;
1155 }
1156 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1157 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1158 file, linenum);
1159 return -1;
1160 }
1161
1162 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1163 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1164 file, linenum);
1165 return -1;
1166 }
1167 }/* end else if (!strcmp(args[0], "cookie")) */
1168 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1171 return 0;
1172
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 if (*(args[5]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1175 file, linenum, args[0]);
1176 return -1;
1177 }
1178 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001179 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 curproxy->appsession_name = strdup(args[1]);
1181 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1182 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001183 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1184 if (err) {
1185 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1186 file, linenum, *err, args[0]);
1187 return -1;
1188 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001189 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001190
Willy Tarreau51041c72007-09-09 21:56:53 +02001191 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 return -1;
1194 }
1195 } /* Url App Session */
1196 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001197 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1198 return 0;
1199
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (*(args[4]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1203 file, linenum, args[0]);
1204 return -1;
1205 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001206 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 curproxy->capture_name = strdup(args[2]);
1208 curproxy->capture_namelen = strlen(curproxy->capture_name);
1209 curproxy->capture_len = atol(args[4]);
1210 if (curproxy->capture_len >= CAPTURE_LEN) {
1211 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1212 file, linenum, CAPTURE_LEN - 1);
1213 curproxy->capture_len = CAPTURE_LEN - 1;
1214 }
1215 curproxy->to_log |= LW_COOKIE;
1216 }
1217 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1218 struct cap_hdr *hdr;
1219
1220 if (curproxy == &defproxy) {
1221 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1222 return -1;
1223 }
1224
1225 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1226 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1227 file, linenum, args[0], args[1]);
1228 return -1;
1229 }
1230
1231 hdr = calloc(sizeof(struct cap_hdr), 1);
1232 hdr->next = curproxy->req_cap;
1233 hdr->name = strdup(args[3]);
1234 hdr->namelen = strlen(args[3]);
1235 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001236 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001237 hdr->index = curproxy->nb_req_cap++;
1238 curproxy->req_cap = hdr;
1239 curproxy->to_log |= LW_REQHDR;
1240 }
1241 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1242 struct cap_hdr *hdr;
1243
1244 if (curproxy == &defproxy) {
1245 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1246 return -1;
1247 }
1248
1249 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1250 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1251 file, linenum, args[0], args[1]);
1252 return -1;
1253 }
1254 hdr = calloc(sizeof(struct cap_hdr), 1);
1255 hdr->next = curproxy->rsp_cap;
1256 hdr->name = strdup(args[3]);
1257 hdr->namelen = strlen(args[3]);
1258 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001259 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 hdr->index = curproxy->nb_rsp_cap++;
1261 curproxy->rsp_cap = hdr;
1262 curproxy->to_log |= LW_RSPHDR;
1263 }
1264 else {
1265 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1266 file, linenum, args[0]);
1267 return -1;
1268 }
1269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1272 return 0;
1273
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 if (*(args[1]) == 0) {
1275 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1276 file, linenum, args[0]);
1277 return -1;
1278 }
1279 curproxy->conn_retries = atol(args[1]);
1280 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001281 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1282 int pol = ACL_COND_NONE;
1283 struct acl_cond *cond;
1284
Willy Tarreaub099aca2008-10-12 17:26:37 +02001285 if (curproxy == &defproxy) {
1286 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1287 return -1;
1288 }
1289
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001290 if (!strcmp(args[1], "if"))
1291 pol = ACL_COND_IF;
1292 else if (!strcmp(args[1], "unless"))
1293 pol = ACL_COND_UNLESS;
1294
1295 if (pol == ACL_COND_NONE) {
1296 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1297 file, linenum, args[0]);
1298 return -1;
1299 }
1300
1301 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1302 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1303 file, linenum);
1304 return -1;
1305 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001306 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001307 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001308 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001309 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001310 else if (!strcmp(args[0], "redirect")) {
1311 int pol = ACL_COND_NONE;
1312 struct acl_cond *cond;
1313 struct redirect_rule *rule;
1314 int cur_arg;
1315 int type = REDIRECT_TYPE_NONE;
1316 int code = 302;
1317 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001318 char *cookie = NULL;
1319 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001320 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001321
1322 cur_arg = 1;
1323 while (*(args[cur_arg])) {
1324 if (!strcmp(args[cur_arg], "location")) {
1325 if (!*args[cur_arg + 1]) {
1326 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1327 file, linenum, args[0], args[cur_arg]);
1328 return -1;
1329 }
1330
1331 type = REDIRECT_TYPE_LOCATION;
1332 cur_arg++;
1333 destination = args[cur_arg];
1334 }
1335 else if (!strcmp(args[cur_arg], "prefix")) {
1336 if (!*args[cur_arg + 1]) {
1337 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1338 file, linenum, args[0], args[cur_arg]);
1339 return -1;
1340 }
1341
1342 type = REDIRECT_TYPE_PREFIX;
1343 cur_arg++;
1344 destination = args[cur_arg];
1345 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001346 else if (!strcmp(args[cur_arg], "set-cookie")) {
1347 if (!*args[cur_arg + 1]) {
1348 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1349 file, linenum, args[0], args[cur_arg]);
1350 return -1;
1351 }
1352
1353 cur_arg++;
1354 cookie = args[cur_arg];
1355 cookie_set = 1;
1356 }
1357 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1358 if (!*args[cur_arg + 1]) {
1359 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1360 file, linenum, args[0], args[cur_arg]);
1361 return -1;
1362 }
1363
1364 cur_arg++;
1365 cookie = args[cur_arg];
1366 cookie_set = 0;
1367 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001368 else if (!strcmp(args[cur_arg],"code")) {
1369 if (!*args[cur_arg + 1]) {
1370 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1371 file, linenum, args[0]);
1372 return -1;
1373 }
1374 cur_arg++;
1375 code = atol(args[cur_arg]);
1376 if (code < 301 || code > 303) {
1377 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1378 file, linenum, args[0], code);
1379 return -1;
1380 }
1381 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001382 else if (!strcmp(args[cur_arg],"drop-query")) {
1383 flags |= REDIRECT_FLAG_DROP_QS;
1384 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001385 else if (!strcmp(args[cur_arg], "if")) {
1386 pol = ACL_COND_IF;
1387 cur_arg++;
1388 break;
1389 }
1390 else if (!strcmp(args[cur_arg], "unless")) {
1391 pol = ACL_COND_UNLESS;
1392 cur_arg++;
1393 break;
1394 }
1395 else {
1396 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1397 file, linenum, args[0], args[cur_arg]);
1398 return -1;
1399 }
1400 cur_arg++;
1401 }
1402
1403 if (type == REDIRECT_TYPE_NONE) {
1404 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1405 file, linenum, args[0]);
1406 return -1;
1407 }
1408
1409 if (pol == ACL_COND_NONE) {
1410 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1411 file, linenum, args[0]);
1412 return -1;
1413 }
1414
1415 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001416 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001417 file, linenum, args[0]);
1418 return -1;
1419 }
1420
Willy Tarreaua9802632008-07-25 19:13:19 +02001421 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001422 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1423 rule->cond = cond;
1424 rule->rdr_str = strdup(destination);
1425 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001426 if (cookie) {
1427 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1428 * a clear consists in appending "; Max-Age=0" at the end.
1429 */
1430 rule->cookie_len = strlen(cookie);
1431 if (cookie_set)
1432 rule->cookie_str = strdup(cookie);
1433 else {
1434 rule->cookie_str = malloc(rule->cookie_len + 12);
1435 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1436 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1437 rule->cookie_len += 11;
1438 }
1439 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001440 rule->type = type;
1441 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001442 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001443 LIST_INIT(&rule->list);
1444 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001445 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001446 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001447 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001448 int pol = ACL_COND_NONE;
1449 struct acl_cond *cond;
1450 struct switching_rule *rule;
1451
Willy Tarreaub099aca2008-10-12 17:26:37 +02001452 if (curproxy == &defproxy) {
1453 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1454 return -1;
1455 }
1456
Willy Tarreau55ea7572007-06-17 19:56:27 +02001457 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1458 return 0;
1459
1460 if (*(args[1]) == 0) {
1461 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1462 return -1;
1463 }
1464
1465 if (!strcmp(args[2], "if"))
1466 pol = ACL_COND_IF;
1467 else if (!strcmp(args[2], "unless"))
1468 pol = ACL_COND_UNLESS;
1469
1470 if (pol == ACL_COND_NONE) {
1471 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1472 file, linenum, args[0]);
1473 return -1;
1474 }
1475
1476 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001477 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001478 file, linenum);
1479 return -1;
1480 }
1481
Willy Tarreaua9802632008-07-25 19:13:19 +02001482 cond->line = linenum;
1483 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001484 struct acl *acl;
1485 const char *name;
1486
1487 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1488 name = acl ? acl->name : "(unknown)";
1489 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1490 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001491 }
1492
Willy Tarreau55ea7572007-06-17 19:56:27 +02001493 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1494 rule->cond = cond;
1495 rule->be.name = strdup(args[1]);
1496 LIST_INIT(&rule->list);
1497 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1501 return 0;
1502
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1504 curproxy->uri_auth = NULL; /* we must detach from the default config */
1505
1506 if (*(args[1]) == 0) {
1507 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1508 return -1;
1509 } else if (!strcmp(args[1], "uri")) {
1510 if (*(args[2]) == 0) {
1511 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1512 return -1;
1513 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1514 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1515 return -1;
1516 }
1517 } else if (!strcmp(args[1], "realm")) {
1518 if (*(args[2]) == 0) {
1519 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1520 return -1;
1521 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1522 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1523 return -1;
1524 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001525 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001526 unsigned interval;
1527
1528 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1529 if (err) {
1530 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1531 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001532 return -1;
1533 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1534 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1535 return -1;
1536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 } else if (!strcmp(args[1], "auth")) {
1538 if (*(args[2]) == 0) {
1539 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1540 return -1;
1541 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1543 return -1;
1544 }
1545 } else if (!strcmp(args[1], "scope")) {
1546 if (*(args[2]) == 0) {
1547 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1548 return -1;
1549 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1551 return -1;
1552 }
1553 } else if (!strcmp(args[1], "enable")) {
1554 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1556 return -1;
1557 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001558 } else if (!strcmp(args[1], "hide-version")) {
1559 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1560 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1561 return -1;
1562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001564 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 file, linenum, args[0]);
1566 return -1;
1567 }
1568 }
1569 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001570 int optnum;
1571
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001572 if (*(args[1]) == '\0') {
1573 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1574 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 return -1;
1576 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001577
1578 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1579 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1580 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1581 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001582
1583 if (!inv)
1584 curproxy->options |= cfg_opts[optnum].val;
1585 else
1586 curproxy->options &= ~cfg_opts[optnum].val;
1587
Willy Tarreau13943ab2006-12-31 00:24:10 +01001588 return 0;
1589 }
1590 }
1591
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001592 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1593 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1594 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1595 return 0;
1596
1597 if (!inv)
1598 curproxy->options2 |= cfg_opts2[optnum].val;
1599 else
1600 curproxy->options2 &= ~cfg_opts2[optnum].val;
1601
1602 return 0;
1603 }
1604 }
1605
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001606 if (inv) {
1607 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1608 file, linenum, args[1]);
1609 return -1;
1610 }
1611
Willy Tarreau13943ab2006-12-31 00:24:10 +01001612 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 /* generate a complete HTTP log */
1614 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1615 else if (!strcmp(args[1], "tcplog"))
1616 /* generate a detailed TCP log */
1617 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 else if (!strcmp(args[1], "tcpka")) {
1619 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001620 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1621 return 0;
1622
1623 if (curproxy->cap & PR_CAP_FE)
1624 curproxy->options |= PR_O_TCP_CLI_KA;
1625 if (curproxy->cap & PR_CAP_BE)
1626 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 }
1628 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001629 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1630 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001632 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001633 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001634 curproxy->options &= ~PR_O_SMTP_CHK;
1635 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 if (!*args[2]) { /* no argument */
1637 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1638 curproxy->check_len = strlen(DEF_CHECK_REQ);
1639 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001640 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 curproxy->check_req = (char *)malloc(reqlen);
1642 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1643 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1644 } else { /* more arguments : METHOD URI [HTTP_VER] */
1645 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1646 if (*args[4])
1647 reqlen += strlen(args[4]);
1648 else
1649 reqlen += strlen("HTTP/1.0");
1650
1651 curproxy->check_req = (char *)malloc(reqlen);
1652 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1653 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1654 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001655 }
1656 else if (!strcmp(args[1], "ssl-hello-chk")) {
1657 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1659 return 0;
1660
Willy Tarreaua534fea2008-08-03 12:19:50 +02001661 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001662 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001663 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001664 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
Willy Tarreau23677902007-05-08 23:50:35 +02001666 else if (!strcmp(args[1], "smtpchk")) {
1667 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001668 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001669 curproxy->options &= ~PR_O_HTTP_CHK;
1670 curproxy->options &= ~PR_O_SSL3_CHK;
1671 curproxy->options |= PR_O_SMTP_CHK;
1672
1673 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1674 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1675 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1676 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1677 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1678 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1679 curproxy->check_req = (char *)malloc(reqlen);
1680 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1681 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1682 } else {
1683 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1684 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1685 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1686 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1687 }
1688 }
1689 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001690 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001691 int cur_arg;
1692
1693 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1694 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001695 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001696
1697 curproxy->options |= PR_O_FWDFOR;
1698
1699 free(curproxy->fwdfor_hdr_name);
1700 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1701 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1702
1703 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1704 cur_arg = 2;
1705 while (*(args[cur_arg])) {
1706 if (!strcmp(args[cur_arg], "except")) {
1707 /* suboption except - needs additional argument for it */
1708 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1709 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1710 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001711 return -1;
1712 }
1713 /* flush useless bits */
1714 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001715 cur_arg += 2;
1716 } else if (!strcmp(args[cur_arg], "header")) {
1717 /* suboption header - needs additional argument for it */
1718 if (*(args[cur_arg+1]) == 0) {
1719 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1720 file, linenum, args[0], args[1], args[cur_arg]);
1721 return -1;
1722 }
1723 free(curproxy->fwdfor_hdr_name);
1724 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1725 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1726 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001727 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001728 /* unknown suboption - catchall */
1729 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1730 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001731 return -1;
1732 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001733 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001734 }
Maik Broemme2850cb42009-04-17 18:53:21 +02001735 else if (!strcmp(args[1], "originalto")) {
1736 int cur_arg;
1737
1738 /* insert x-original-to field, but not for the IP address listed as an except.
1739 * set default options (ie: bitfield, header name, etc)
1740 */
1741
1742 curproxy->options |= PR_O_ORGTO;
1743
1744 free(curproxy->orgto_hdr_name);
1745 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
1746 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
1747
1748 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1749 cur_arg = 2;
1750 while (*(args[cur_arg])) {
1751 if (!strcmp(args[cur_arg], "except")) {
1752 /* suboption except - needs additional argument for it */
1753 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
1754 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1755 file, linenum, args[0], args[1], args[cur_arg]);
1756 return -1;
1757 }
1758 /* flush useless bits */
1759 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
1760 cur_arg += 2;
1761 } else if (!strcmp(args[cur_arg], "header")) {
1762 /* suboption header - needs additional argument for it */
1763 if (*(args[cur_arg+1]) == 0) {
1764 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1765 file, linenum, args[0], args[1], args[cur_arg]);
1766 return -1;
1767 }
1768 free(curproxy->orgto_hdr_name);
1769 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
1770 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
1771 cur_arg += 2;
1772 } else {
1773 /* unknown suboption - catchall */
1774 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1775 file, linenum, args[0], args[1]);
1776 return -1;
1777 }
1778 } /* end while loop */
1779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 else {
1781 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1782 return -1;
1783 }
1784 return 0;
1785 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001786 else if (!strcmp(args[0], "default_backend")) {
1787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1788 return 0;
1789
1790 if (*(args[1]) == 0) {
1791 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1792 return -1;
1793 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001794 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001795 curproxy->defbe.name = strdup(args[1]);
1796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1799 return 0;
1800
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001801 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1802 file, linenum, args[0]);
1803
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 /* enable reconnections to dispatch */
1805 curproxy->options |= PR_O_REDISP;
1806 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001807 else if (!strcmp(args[0], "http-check")) {
1808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1809 return 0;
1810
1811 if (strcmp(args[1], "disable-on-404") == 0) {
1812 /* enable a graceful server shutdown on an HTTP 404 response */
1813 curproxy->options |= PR_O_DISABLE404;
1814 }
1815 else {
1816 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1817 return -1;
1818 }
1819 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001820 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001821 if (curproxy == &defproxy) {
1822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1823 return -1;
1824 }
1825
Willy Tarreaub80c2302007-11-30 20:51:32 +01001826 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1827 return 0;
1828
1829 if (strcmp(args[1], "fail") == 0) {
1830 /* add a condition to fail monitor requests */
1831 int pol = ACL_COND_NONE;
1832 struct acl_cond *cond;
1833
1834 if (!strcmp(args[2], "if"))
1835 pol = ACL_COND_IF;
1836 else if (!strcmp(args[2], "unless"))
1837 pol = ACL_COND_UNLESS;
1838
1839 if (pol == ACL_COND_NONE) {
1840 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1841 file, linenum, args[0], args[1]);
1842 return -1;
1843 }
1844
1845 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1846 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1847 file, linenum, args[0], args[1]);
1848 return -1;
1849 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001850 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001851 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1852 }
1853 else {
1854 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1855 return -1;
1856 }
1857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858#ifdef TPROXY
1859 else if (!strcmp(args[0], "transparent")) {
1860 /* enable transparent proxy connections */
1861 curproxy->options |= PR_O_TRANSP;
1862 }
1863#endif
1864 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1866 return 0;
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 if (*(args[1]) == 0) {
1869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1870 return -1;
1871 }
1872 curproxy->maxconn = atol(args[1]);
1873 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001874 else if (!strcmp(args[0], "backlog")) { /* backlog */
1875 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1876 return 0;
1877
1878 if (*(args[1]) == 0) {
1879 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1880 return -1;
1881 }
1882 curproxy->backlog = atol(args[1]);
1883 }
Willy Tarreau86034312006-12-29 00:10:33 +01001884 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001885 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1886 return 0;
1887
Willy Tarreau86034312006-12-29 00:10:33 +01001888 if (*(args[1]) == 0) {
1889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1890 return -1;
1891 }
1892 curproxy->fullconn = atol(args[1]);
1893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1895 if (*(args[1]) == 0) {
1896 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1897 return -1;
1898 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001899 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1900 if (err) {
1901 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1902 file, linenum, *err);
1903 return -1;
1904 }
1905 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 }
1907 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1908 if (curproxy == &defproxy) {
1909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1910 return -1;
1911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001912 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1913 return 0;
1914
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 if (strchr(args[1], ':') == NULL) {
1916 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1917 return -1;
1918 }
1919 curproxy->dispatch_addr = *str2sa(args[1]);
1920 }
1921 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1923 return 0;
1924
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001925 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001926 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1927 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1928 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 }
1931 else if (!strcmp(args[0], "server")) { /* server address */
1932 int cur_arg;
1933 char *rport;
1934 char *raddr;
1935 short realport;
1936 int do_check;
1937
1938 if (curproxy == &defproxy) {
1939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1940 return -1;
1941 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1943 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944
1945 if (!*args[2]) {
1946 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1947 file, linenum, args[0]);
1948 return -1;
1949 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001950
1951 err = invalid_char(args[1]);
1952 if (err) {
1953 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1954 file, linenum, *err, args[1]);
1955 return -1;
1956 }
1957
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1959 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1960 return -1;
1961 }
1962
1963 /* the servers are linked backwards first */
1964 newsrv->next = curproxy->srv;
1965 curproxy->srv = newsrv;
1966 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001967 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968
1969 LIST_INIT(&newsrv->pendconns);
1970 do_check = 0;
1971 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001972 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 newsrv->id = strdup(args[1]);
1974
1975 /* several ways to check the port component :
1976 * - IP => port=+0, relative
1977 * - IP: => port=+0, relative
1978 * - IP:N => port=N, absolute
1979 * - IP:+N => port=+N, relative
1980 * - IP:-N => port=-N, relative
1981 */
1982 raddr = strdup(args[2]);
1983 rport = strchr(raddr, ':');
1984 if (rport) {
1985 *rport++ = 0;
1986 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001987 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 newsrv->state |= SRV_MAPPORTS;
1989 } else {
1990 realport = 0;
1991 newsrv->state |= SRV_MAPPORTS;
1992 }
1993
1994 newsrv->addr = *str2sa(raddr);
1995 newsrv->addr.sin_port = htons(realport);
1996 free(raddr);
1997
1998 newsrv->curfd = -1; /* no health-check in progress */
1999 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002000 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2001 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 newsrv->rise = DEF_RISETIME;
2003 newsrv->fall = DEF_FALLTIME;
2004 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002005 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002006 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002007 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002008
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 cur_arg = 3;
2010 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002011 if (!strcmp(args[cur_arg], "id")) {
2012 struct server *target;
2013
2014 if (!*args[cur_arg + 1]) {
2015 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2016 file, linenum, args[cur_arg]);
2017 return -1;
2018 }
2019
2020 newsrv->puid = atol(args[cur_arg + 1]);
2021
2022 if (newsrv->puid< 1001) {
2023 Alert("parsing [%s:%d]: custom id has to be > 1000",
2024 file, linenum);
2025 return -1;
2026 }
2027
2028 for (target = proxy->srv; target; target = target->next)
2029 if (newsrv != target && newsrv->puid == target->puid) {
2030 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2031 file, linenum, newsrv->id, target->id);
2032 return -1;
2033 }
2034 cur_arg += 2;
2035 }
2036 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 newsrv->cookie = strdup(args[cur_arg + 1]);
2038 newsrv->cklen = strlen(args[cur_arg + 1]);
2039 cur_arg += 2;
2040 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002041 else if (!strcmp(args[cur_arg], "redir")) {
2042 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2043 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2044 cur_arg += 2;
2045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 else if (!strcmp(args[cur_arg], "rise")) {
2047 newsrv->rise = atol(args[cur_arg + 1]);
2048 newsrv->health = newsrv->rise;
2049 cur_arg += 2;
2050 }
2051 else if (!strcmp(args[cur_arg], "fall")) {
2052 newsrv->fall = atol(args[cur_arg + 1]);
2053 cur_arg += 2;
2054 }
2055 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002056 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2057 if (err) {
2058 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2059 file, linenum, *err, newsrv->id);
2060 return -1;
2061 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002062 if (val <= 0) {
2063 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2064 file, linenum, val, args[cur_arg], newsrv->id);
2065 return -1;
2066 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002067 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 cur_arg += 2;
2069 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002070 else if (!strcmp(args[cur_arg], "fastinter")) {
2071 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2072 if (err) {
2073 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2074 file, linenum, *err, newsrv->id);
2075 return -1;
2076 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002077 if (val <= 0) {
2078 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2079 file, linenum, val, args[cur_arg], newsrv->id);
2080 return -1;
2081 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002082 newsrv->fastinter = val;
2083 cur_arg += 2;
2084 }
2085 else if (!strcmp(args[cur_arg], "downinter")) {
2086 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2087 if (err) {
2088 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2089 file, linenum, *err, newsrv->id);
2090 return -1;
2091 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002092 if (val <= 0) {
2093 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2094 file, linenum, val, args[cur_arg], newsrv->id);
2095 return -1;
2096 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002097 newsrv->downinter = val;
2098 cur_arg += 2;
2099 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002100 else if (!strcmp(args[cur_arg], "addr")) {
2101 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002102 cur_arg += 2;
2103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 else if (!strcmp(args[cur_arg], "port")) {
2105 newsrv->check_port = atol(args[cur_arg + 1]);
2106 cur_arg += 2;
2107 }
2108 else if (!strcmp(args[cur_arg], "backup")) {
2109 newsrv->state |= SRV_BACKUP;
2110 cur_arg ++;
2111 }
2112 else if (!strcmp(args[cur_arg], "weight")) {
2113 int w;
2114 w = atol(args[cur_arg + 1]);
2115 if (w < 1 || w > 256) {
2116 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
2117 file, linenum, newsrv->id, w);
2118 return -1;
2119 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002120 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 cur_arg += 2;
2122 }
2123 else if (!strcmp(args[cur_arg], "minconn")) {
2124 newsrv->minconn = atol(args[cur_arg + 1]);
2125 cur_arg += 2;
2126 }
2127 else if (!strcmp(args[cur_arg], "maxconn")) {
2128 newsrv->maxconn = atol(args[cur_arg + 1]);
2129 cur_arg += 2;
2130 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002131 else if (!strcmp(args[cur_arg], "maxqueue")) {
2132 newsrv->maxqueue = atol(args[cur_arg + 1]);
2133 cur_arg += 2;
2134 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002135 else if (!strcmp(args[cur_arg], "slowstart")) {
2136 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002137 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002138 if (err) {
2139 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2140 file, linenum, *err, newsrv->id);
2141 return -1;
2142 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002143 if (val <= 0) {
2144 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2145 file, linenum, val, args[cur_arg], newsrv->id);
2146 return -1;
2147 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002148 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002149 cur_arg += 2;
2150 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002151 else if (!strcmp(args[cur_arg], "track")) {
2152
2153 if (!*args[cur_arg + 1]) {
2154 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2155 file, linenum);
2156 return -1;
2157 }
2158
2159 newsrv->trackit = strdup(args[cur_arg + 1]);
2160
2161 cur_arg += 2;
2162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 else if (!strcmp(args[cur_arg], "check")) {
2164 global.maxsock++;
2165 do_check = 1;
2166 cur_arg += 1;
2167 }
2168 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2169 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002170#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002171 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2172 file, linenum, "source", "usesrc");
2173#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2175 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002176#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 return -1;
2178 }
2179 newsrv->state |= SRV_BIND_SRC;
2180 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2181 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002182 while (*(args[cur_arg])) {
2183 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002184#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2185#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002186 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2187 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2188 file, linenum, "usesrc", "source");
2189 return -1;
2190 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002191#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002192 if (!*args[cur_arg + 1]) {
2193 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2194 file, linenum, "usesrc");
2195 return -1;
2196 }
2197 if (!strcmp(args[cur_arg + 1], "client")) {
2198 newsrv->state |= SRV_TPROXY_CLI;
2199 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2200 newsrv->state |= SRV_TPROXY_CIP;
2201 } else {
2202 newsrv->state |= SRV_TPROXY_ADDR;
2203 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2204 }
2205 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002206#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002207 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002208#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002209 cur_arg += 2;
2210 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002211#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002212 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002213 file, linenum, "usesrc");
2214 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002215#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2216 } /* "usesrc" */
2217
2218 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2219#ifdef SO_BINDTODEVICE
2220 if (!*args[cur_arg + 1]) {
2221 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2222 file, linenum, args[0]);
2223 return -1;
2224 }
2225 if (newsrv->iface_name)
2226 free(newsrv->iface_name);
2227
2228 newsrv->iface_name = strdup(args[cur_arg + 1]);
2229 newsrv->iface_len = strlen(newsrv->iface_name);
2230 global.last_checks |= LSTCHK_NETADM;
2231#else
2232 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2233 file, linenum, args[0], args[cur_arg]);
2234 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002235#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002236 cur_arg += 2;
2237 continue;
2238 }
2239 /* this keyword in not an option of "source" */
2240 break;
2241 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002243 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2244 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2245 file, linenum, "usesrc", "source");
2246 return -1;
2247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002249 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 +02002250 file, linenum, newsrv->id);
2251 return -1;
2252 }
2253 }
2254
2255 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002256 if (newsrv->trackit) {
2257 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2258 file, linenum);
2259 return -1;
2260 }
2261
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002262 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2263 newsrv->check_port = newsrv->check_addr.sin_port;
2264
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2266 newsrv->check_port = realport; /* by default */
2267 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002268 /* not yet valid, because no port was set on
2269 * the server either. We'll check if we have
2270 * a known port on the first listener.
2271 */
2272 struct listener *l;
2273 l = curproxy->listen;
2274 if (l) {
2275 int port;
2276 port = (l->addr.ss_family == AF_INET6)
2277 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2278 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2279 newsrv->check_port = port;
2280 }
2281 }
2282 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2284 file, linenum, newsrv->id);
2285 return -1;
2286 }
2287 newsrv->state |= SRV_CHECKED;
2288 }
2289
2290 if (newsrv->state & SRV_BACKUP)
2291 curproxy->srv_bck++;
2292 else
2293 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002294
2295 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 }
2297 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002298 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 int facility;
2300
2301 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2302 curproxy->logfac1 = global.logfac1;
2303 curproxy->logsrv1 = global.logsrv1;
2304 curproxy->loglev1 = global.loglev1;
2305 curproxy->logfac2 = global.logfac2;
2306 curproxy->logsrv2 = global.logsrv2;
2307 curproxy->loglev2 = global.loglev2;
2308 }
2309 else if (*(args[1]) && *(args[2])) {
2310 int level;
2311
2312 facility = get_log_facility(args[2]);
2313 if (facility < 0) {
2314 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2315 exit(1);
2316 }
2317
2318 level = 7; /* max syslog level = debug */
2319 if (*(args[3])) {
2320 level = get_log_level(args[3]);
2321 if (level < 0) {
2322 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2323 exit(1);
2324 }
2325 }
2326
Robert Tsai81ae1952007-12-05 10:47:29 +01002327 if (args[1][0] == '/') {
2328 logsrv.u.addr.sa_family = AF_UNIX;
2329 logsrv.u.un = *str2sun(args[1]);
2330 } else {
2331 logsrv.u.addr.sa_family = AF_INET;
2332 logsrv.u.in = *str2sa(args[1]);
2333 if (!logsrv.u.in.sin_port) {
2334 logsrv.u.in.sin_port =
2335 htons(SYSLOG_PORT);
2336 }
2337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338
2339 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002340 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 curproxy->logfac1 = facility;
2342 curproxy->loglev1 = level;
2343 }
2344 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002345 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->logfac2 = facility;
2347 curproxy->loglev2 = level;
2348 }
2349 else {
2350 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2351 return -1;
2352 }
2353 }
2354 else {
2355 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2356 file, linenum);
2357 return -1;
2358 }
2359 }
2360 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002361 int cur_arg;
2362
Willy Tarreau977b8e42006-12-29 14:19:17 +01002363 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2364 return 0;
2365
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002367 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2368 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 return -1;
2370 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002371
2372 /* we must first clear any optional default setting */
2373 curproxy->options &= ~PR_O_TPXY_MASK;
2374 free(curproxy->iface_name);
2375 curproxy->iface_name = NULL;
2376 curproxy->iface_len = 0;
2377
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 curproxy->source_addr = *str2sa(args[1]);
2379 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002380
2381 cur_arg = 2;
2382 while (*(args[cur_arg])) {
2383 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002384#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2385#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002386 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2387 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2388 file, linenum, "usesrc");
2389 return -1;
2390 }
2391#endif
2392 if (!*args[cur_arg + 1]) {
2393 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2394 file, linenum, "usesrc");
2395 return -1;
2396 }
2397
2398 if (!strcmp(args[cur_arg + 1], "client")) {
2399 curproxy->options |= PR_O_TPXY_CLI;
2400 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2401 curproxy->options |= PR_O_TPXY_CIP;
2402 } else {
2403 curproxy->options |= PR_O_TPXY_ADDR;
2404 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2405 }
2406 global.last_checks |= LSTCHK_NETADM;
2407#if !defined(CONFIG_HAP_LINUX_TPROXY)
2408 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002409#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002410#else /* no TPROXY support */
2411 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002412 file, linenum, "usesrc");
2413 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002414#endif
2415 cur_arg += 2;
2416 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002417 }
2418
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002419 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2420#ifdef SO_BINDTODEVICE
2421 if (!*args[cur_arg + 1]) {
2422 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2423 file, linenum, args[0]);
2424 return -1;
2425 }
2426 if (curproxy->iface_name)
2427 free(curproxy->iface_name);
2428
2429 curproxy->iface_name = strdup(args[cur_arg + 1]);
2430 curproxy->iface_len = strlen(curproxy->iface_name);
2431 global.last_checks |= LSTCHK_NETADM;
2432#else
2433 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2434 file, linenum, args[0], args[cur_arg]);
2435 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002436#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002437 cur_arg += 2;
2438 continue;
2439 }
2440 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2441 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002442 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002445 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2446 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2447 file, linenum, "usesrc", "source");
2448 return -1;
2449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2451 regex_t *preg;
2452 if (curproxy == &defproxy) {
2453 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2454 return -1;
2455 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002456 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2457 return 0;
2458
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 if (*(args[1]) == 0 || *(args[2]) == 0) {
2460 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2461 file, linenum, args[0]);
2462 return -1;
2463 }
2464
2465 preg = calloc(1, sizeof(regex_t));
2466 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2467 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2468 return -1;
2469 }
2470
2471 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2472 if (err) {
2473 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2474 file, linenum, *err);
2475 return -1;
2476 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002477 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2480 regex_t *preg;
2481 if (curproxy == &defproxy) {
2482 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2483 return -1;
2484 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002485 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2486 return 0;
2487
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 if (*(args[1]) == 0) {
2489 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2490 return -1;
2491 }
2492
2493 preg = calloc(1, sizeof(regex_t));
2494 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2495 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2496 return -1;
2497 }
2498
2499 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002500 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
2502 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2503 regex_t *preg;
2504 if (curproxy == &defproxy) {
2505 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2506 return -1;
2507 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002508 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2509 return 0;
2510
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 if (*(args[1]) == 0) {
2512 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2513 return -1;
2514 }
2515
2516 preg = calloc(1, sizeof(regex_t));
2517 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2518 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2519 return -1;
2520 }
2521
2522 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002523 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 }
2525 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2526 regex_t *preg;
2527 if (curproxy == &defproxy) {
2528 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2529 return -1;
2530 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002531 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2532 return 0;
2533
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 if (*(args[1]) == 0) {
2535 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2536 return -1;
2537 }
2538
2539 preg = calloc(1, sizeof(regex_t));
2540 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2541 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2542 return -1;
2543 }
2544
2545 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002546 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 }
2548 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2549 regex_t *preg;
2550 if (curproxy == &defproxy) {
2551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2552 return -1;
2553 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002554 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2555 return 0;
2556
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 if (*(args[1]) == 0) {
2558 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2559 return -1;
2560 }
2561
2562 preg = calloc(1, sizeof(regex_t));
2563 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2564 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2565 return -1;
2566 }
2567
2568 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002569 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002571 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2572 regex_t *preg;
2573 if (curproxy == &defproxy) {
2574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2575 return -1;
2576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2578 return 0;
2579
Willy Tarreaub8750a82006-09-03 09:56:00 +02002580 if (*(args[1]) == 0) {
2581 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2582 return -1;
2583 }
2584
2585 preg = calloc(1, sizeof(regex_t));
2586 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2587 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2588 return -1;
2589 }
2590
2591 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002592 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002593 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002594 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2595 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002596 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002597 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2598 return -1;
2599 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2601 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002602
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002604 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2605 file, linenum, args[0]);
2606 return -1;
2607 }
2608
2609 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002610 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002611 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2612 }
2613
2614 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002615 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002616 }
2617 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2618 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002619 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002620 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2621 return -1;
2622 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2624 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002625
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002627 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2628 file, linenum, args[0]);
2629 return -1;
2630 }
2631
2632 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002634 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2635 }
2636
2637 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002638 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2641 regex_t *preg;
2642 if (curproxy == &defproxy) {
2643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2644 return -1;
2645 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2647 return 0;
2648
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 if (*(args[1]) == 0 || *(args[2]) == 0) {
2650 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2651 file, linenum, args[0]);
2652 return -1;
2653 }
2654
2655 preg = calloc(1, sizeof(regex_t));
2656 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2657 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2658 return -1;
2659 }
2660
2661 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2662 if (err) {
2663 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2664 file, linenum, *err);
2665 return -1;
2666 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002667 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 }
2669 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2670 regex_t *preg;
2671 if (curproxy == &defproxy) {
2672 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2673 return -1;
2674 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002675 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2676 return 0;
2677
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 if (*(args[1]) == 0) {
2679 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2680 return -1;
2681 }
2682
2683 preg = calloc(1, sizeof(regex_t));
2684 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2685 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2686 return -1;
2687 }
2688
2689 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002690 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2693 regex_t *preg;
2694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2696 return -1;
2697 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2699 return 0;
2700
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 if (*(args[1]) == 0) {
2702 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2703 return -1;
2704 }
2705
2706 preg = calloc(1, sizeof(regex_t));
2707 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2708 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2709 return -1;
2710 }
2711
2712 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002713 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 }
2715 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2716 regex_t *preg;
2717 if (curproxy == &defproxy) {
2718 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2719 return -1;
2720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2722 return 0;
2723
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 if (*(args[1]) == 0) {
2725 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2726 return -1;
2727 }
2728
2729 preg = calloc(1, sizeof(regex_t));
2730 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2731 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2732 return -1;
2733 }
2734
2735 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002736 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 }
2738 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2739 regex_t *preg;
2740 if (curproxy == &defproxy) {
2741 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2742 return -1;
2743 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2745 return 0;
2746
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 if (*(args[1]) == 0) {
2748 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2749 return -1;
2750 }
2751
2752 preg = calloc(1, sizeof(regex_t));
2753 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2754 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2755 return -1;
2756 }
2757
2758 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002759 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002761 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2762 regex_t *preg;
2763 if (curproxy == &defproxy) {
2764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2765 return -1;
2766 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002767 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2768 return 0;
2769
Willy Tarreaub8750a82006-09-03 09:56:00 +02002770 if (*(args[1]) == 0) {
2771 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2772 return -1;
2773 }
2774
2775 preg = calloc(1, sizeof(regex_t));
2776 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2777 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2778 return -1;
2779 }
2780
2781 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002782 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2785 if (curproxy == &defproxy) {
2786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2787 return -1;
2788 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2790 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791
2792 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2793 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2794 return 0;
2795 }
2796
2797 if (*(args[1]) == 0) {
2798 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2799 return -1;
2800 }
2801
2802 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002803 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002804 }
2805 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2806 regex_t *preg;
2807
2808 if (*(args[1]) == 0 || *(args[2]) == 0) {
2809 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2810 file, linenum, args[0]);
2811 return -1;
2812 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002813 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2814 return 0;
2815
Willy Tarreaubaaee002006-06-26 02:48:02 +02002816 preg = calloc(1, sizeof(regex_t));
2817 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2818 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2819 return -1;
2820 }
2821
2822 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2823 if (err) {
2824 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2825 file, linenum, *err);
2826 return -1;
2827 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002828 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 }
2830 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2831 regex_t *preg;
2832 if (curproxy == &defproxy) {
2833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2834 return -1;
2835 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002836 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2837 return 0;
2838
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 if (*(args[1]) == 0) {
2840 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2841 return -1;
2842 }
2843
2844 preg = calloc(1, sizeof(regex_t));
2845 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2846 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2847 return -1;
2848 }
2849
2850 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2851 if (err) {
2852 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2853 file, linenum, *err);
2854 return -1;
2855 }
2856 }
2857 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2858 regex_t *preg;
2859 if (curproxy == &defproxy) {
2860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2861 return -1;
2862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2864 return 0;
2865
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 if (*(args[1]) == 0) {
2867 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2868 return -1;
2869 }
2870
2871 preg = calloc(1, sizeof(regex_t));
2872 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2873 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2874 return -1;
2875 }
2876
2877 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2878 if (err) {
2879 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2880 file, linenum, *err);
2881 return -1;
2882 }
2883 }
2884 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2885 regex_t *preg;
2886 if (curproxy == &defproxy) {
2887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2888 return -1;
2889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002890 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2891 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892
2893 if (*(args[1]) == 0 || *(args[2]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2895 file, linenum, args[0]);
2896 return -1;
2897 }
2898
2899 preg = calloc(1, sizeof(regex_t));
2900 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2901 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2902 return -1;
2903 }
2904
2905 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2906 if (err) {
2907 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2908 file, linenum, *err);
2909 return -1;
2910 }
2911 }
2912 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2913 regex_t *preg;
2914 if (curproxy == &defproxy) {
2915 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2916 return -1;
2917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002918 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2919 return 0;
2920
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 if (*(args[1]) == 0) {
2922 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2923 return -1;
2924 }
2925
2926 preg = calloc(1, sizeof(regex_t));
2927 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2928 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2929 return -1;
2930 }
2931
2932 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2933 if (err) {
2934 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2935 file, linenum, *err);
2936 return -1;
2937 }
2938 }
2939 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2940 regex_t *preg;
2941 if (curproxy == &defproxy) {
2942 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2943 return -1;
2944 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002945 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2946 return 0;
2947
Willy Tarreaubaaee002006-06-26 02:48:02 +02002948 if (*(args[1]) == 0) {
2949 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2950 return -1;
2951 }
2952
2953 preg = calloc(1, sizeof(regex_t));
2954 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2955 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2956 return -1;
2957 }
2958
2959 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2960 if (err) {
2961 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2962 file, linenum, *err);
2963 return -1;
2964 }
2965 }
2966 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2967 if (curproxy == &defproxy) {
2968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2969 return -1;
2970 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002971 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2972 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973
2974 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2975 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2976 return 0;
2977 }
2978
2979 if (*(args[1]) == 0) {
2980 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2981 return -1;
2982 }
2983
2984 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2985 }
2986 else if (!strcmp(args[0], "errorloc") ||
2987 !strcmp(args[0], "errorloc302") ||
2988 !strcmp(args[0], "errorloc303")) { /* error location */
2989 int errnum, errlen;
2990 char *err;
2991
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2993 return 0;
2994
Willy Tarreaubaaee002006-06-26 02:48:02 +02002995 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02002996 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 return -1;
2998 }
2999
3000 errnum = atol(args[1]);
3001 if (!strcmp(args[0], "errorloc303")) {
3002 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3003 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3004 } else {
3005 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3006 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3007 }
3008
Willy Tarreau0f772532006-12-23 20:51:41 +01003009 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3010 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003011 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003012 curproxy->errmsg[rc].str = err;
3013 curproxy->errmsg[rc].len = errlen;
3014 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003017
3018 if (rc >= HTTP_ERR_SIZE) {
3019 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3020 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 free(err);
3022 }
3023 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003024 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3025 int errnum, errlen, fd;
3026 char *err;
3027 struct stat stat;
3028
3029 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3030 return 0;
3031
3032 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003033 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003034 return -1;
3035 }
3036
3037 fd = open(args[2], O_RDONLY);
3038 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3039 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3040 file, linenum, args[2], args[1]);
3041 if (fd >= 0)
3042 close(fd);
3043 return -1;
3044 }
3045
3046 if (stat.st_size <= BUFSIZE) {
3047 errlen = stat.st_size;
3048 } else {
3049 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3050 file, linenum, args[2], BUFSIZE);
3051 errlen = BUFSIZE;
3052 }
3053
3054 err = malloc(errlen); /* malloc() must succeed during parsing */
3055 errnum = read(fd, err, errlen);
3056 if (errnum != errlen) {
3057 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3058 file, linenum, args[2], args[1]);
3059 close(fd);
3060 free(err);
3061 return -1;
3062 }
3063 close(fd);
3064
3065 errnum = atol(args[1]);
3066 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3067 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003068 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003069 curproxy->errmsg[rc].str = err;
3070 curproxy->errmsg[rc].len = errlen;
3071 break;
3072 }
3073 }
3074
3075 if (rc >= HTTP_ERR_SIZE) {
3076 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3077 file, linenum, errnum);
3078 free(err);
3079 }
3080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003082 struct cfg_kw_list *kwl;
3083 int index;
3084
3085 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3086 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3087 if (kwl->kw[index].section != CFG_LISTEN)
3088 continue;
3089 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3090 /* prepare error message just in case */
3091 snprintf(trash, sizeof(trash),
3092 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003093 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3094 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003095 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3096 return -1;
3097 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003098 else if (rc > 0) {
3099 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3100 return 0;
3101 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003102 return 0;
3103 }
3104 }
3105 }
3106
Willy Tarreau6daf3432008-01-22 16:44:08 +01003107 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 return -1;
3109 }
3110 return 0;
3111}
3112
3113
3114/*
3115 * This function reads and parses the configuration file given in the argument.
3116 * returns 0 if OK, -1 if error.
3117 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003118int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003120 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 FILE *f;
3122 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 int confsect = CFG_NONE;
3125
3126 struct proxy *curproxy = NULL;
3127 struct server *newsrv = NULL;
3128
3129 if ((f=fopen(file,"r")) == NULL)
3130 return -1;
3131
3132 init_default_instance();
3133
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003134 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003135 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003136 char *end;
3137 char *args[MAX_LINE_ARGS + 1];
3138 char *line = thisline;
3139
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 linenum++;
3141
3142 end = line + strlen(line);
3143
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003144 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3145 /* Check if we reached the limit and the last char is not \n.
3146 * Watch out for the last line without the terminating '\n'!
3147 */
3148 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003149 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003150 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003151 }
3152
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003154 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 line++;
3156
3157 arg = 0;
3158 args[arg] = line;
3159
3160 while (*line && arg < MAX_LINE_ARGS) {
3161 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3162 * C equivalent value. Other combinations left unchanged (eg: \1).
3163 */
3164 if (*line == '\\') {
3165 int skip = 0;
3166 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3167 *line = line[1];
3168 skip = 1;
3169 }
3170 else if (line[1] == 'r') {
3171 *line = '\r';
3172 skip = 1;
3173 }
3174 else if (line[1] == 'n') {
3175 *line = '\n';
3176 skip = 1;
3177 }
3178 else if (line[1] == 't') {
3179 *line = '\t';
3180 skip = 1;
3181 }
3182 else if (line[1] == 'x') {
3183 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3184 unsigned char hex1, hex2;
3185 hex1 = toupper(line[2]) - '0';
3186 hex2 = toupper(line[3]) - '0';
3187 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3188 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3189 *line = (hex1<<4) + hex2;
3190 skip = 3;
3191 }
3192 else {
3193 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003194 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 }
3197 if (skip) {
3198 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3199 end -= skip;
3200 }
3201 line++;
3202 }
3203 else if (*line == '#' || *line == '\n' || *line == '\r') {
3204 /* end of string, end of loop */
3205 *line = 0;
3206 break;
3207 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003208 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003210 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003211 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 line++;
3213 args[++arg] = line;
3214 }
3215 else {
3216 line++;
3217 }
3218 }
3219
3220 /* empty line */
3221 if (!**args)
3222 continue;
3223
Willy Tarreau540abe42007-05-02 20:50:16 +02003224 /* zero out remaining args and ensure that at least one entry
3225 * is zeroed out.
3226 */
3227 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 args[arg] = line;
3229 }
3230
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003231 if (!strcmp(args[0], "no")) {
3232 inv = 1;
3233 for (arg=0; *args[arg+1]; arg++)
3234 args[arg] = args[arg+1]; // shift args after inversion
3235 }
3236
3237 if (inv && strcmp(args[0], "option")) {
3238 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003239 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003240 }
3241
Willy Tarreau977b8e42006-12-29 14:19:17 +01003242 if (!strcmp(args[0], "listen") ||
3243 !strcmp(args[0], "frontend") ||
3244 !strcmp(args[0], "backend") ||
3245 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003246 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003248 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003249 cursection = strdup(args[0]);
3250 }
3251 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003253 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003254 cursection = strdup(args[0]);
3255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 /* else it's a section keyword */
3257
3258 switch (confsect) {
3259 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003260 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003261 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 break;
3263 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003264 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003265 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 break;
3267 default:
3268 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003269 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003272 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003273 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 fclose(f);
3275
3276 /*
3277 * Now, check for the integrity of all that we have collected.
3278 */
3279
3280 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003281 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003283 /* first, we will invert the proxy list order */
3284 curproxy = NULL;
3285 while (proxy) {
3286 struct proxy *next;
3287
3288 next = proxy->next;
3289 proxy->next = curproxy;
3290 curproxy = proxy;
3291 if (!next)
3292 break;
3293 proxy = next;
3294 }
3295
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if ((curproxy = proxy) == NULL) {
3297 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3298 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003299 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
3301
3302 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003303 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003304 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003305
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003307 /* ensure we don't keep listeners uselessly bound */
3308 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 curproxy = curproxy->next;
3310 continue;
3311 }
3312
Willy Tarreauff01a212009-03-15 13:46:16 +01003313 switch (curproxy->mode) {
3314 case PR_MODE_HEALTH:
3315 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3316 if (!(curproxy->cap & PR_CAP_FE)) {
3317 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3318 file, proxy_type_str(curproxy), curproxy->id);
3319 cfgerr++;
3320 }
3321
3322 if (curproxy->srv != NULL)
3323 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3324 file, proxy_type_str(curproxy), curproxy->id);
3325 break;
3326
3327 case PR_MODE_TCP:
3328 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3329 break;
3330
3331 case PR_MODE_HTTP:
3332 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3333 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3334 file, curproxy->id);
3335 cfgerr++;
3336 }
3337 break;
3338 }
3339
3340 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003341 Alert("parsing %s : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003342 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 cfgerr++;
3344 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003345
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003346 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3347 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3348 if (curproxy->options & PR_O_TRANSP) {
3349 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3350 file, proxy_type_str(curproxy), curproxy->id);
3351 cfgerr++;
3352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003354 else if (curproxy->srv == NULL) {
3355 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3356 file, proxy_type_str(curproxy), curproxy->id);
3357 cfgerr++;
3358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003360 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3361 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3362 file, proxy_type_str(curproxy), curproxy->id);
3363 }
3364 }
3365 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3366 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3367 /* If no LB algo is set in a backend, and we're not in
3368 * transparent mode, dispatch mode nor proxy mode, we
3369 * want to use balance roundrobin by default.
3370 */
3371 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3372 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003375
Willy Tarreau82936582007-11-30 15:20:09 +01003376 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3377 curproxy->options &= ~PR_O_DISABLE404;
3378 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3379 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3380 }
3381
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003382 /* if a default backend was specified, let's find it */
3383 if (curproxy->defbe.name) {
3384 struct proxy *target;
3385
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003386 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3387 if (!target) {
3388 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3389 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003390 cfgerr++;
3391 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003392 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3393 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003394 } else {
3395 free(curproxy->defbe.name);
3396 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003397 /* we force the backend to be present on at least all of
3398 * the frontend's processes.
3399 */
3400 target->bind_proc = curproxy->bind_proc ?
3401 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 }
3404
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003405 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003406 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3407 /* map jump target for ACT_SETBE in req_rep chain */
3408 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003409 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003410 struct proxy *target;
3411
Willy Tarreaua496b602006-12-17 23:15:24 +01003412 if (exp->action != ACT_SETBE)
3413 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003414
3415 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3416 if (!target) {
3417 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3418 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003419 cfgerr++;
3420 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003421 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3422 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003423 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003424 } else {
3425 free((void *)exp->replace);
3426 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003427 /* we force the backend to be present on at least all of
3428 * the frontend's processes.
3429 */
3430 target->bind_proc = curproxy->bind_proc ?
3431 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003432 }
3433 }
3434 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003435
3436 /* find the target proxy for 'use_backend' rules */
3437 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003438 struct proxy *target;
3439
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003440 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003441
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003442 if (!target) {
3443 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3444 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003445 cfgerr++;
3446 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003447 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3448 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003449 cfgerr++;
3450 } else {
3451 free((void *)rule->be.name);
3452 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003453 /* we force the backend to be present on at least all of
3454 * the frontend's processes.
3455 */
3456 target->bind_proc = curproxy->bind_proc ?
3457 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003458 }
3459 }
3460
Willy Tarreau2738a142006-07-08 17:28:09 +02003461 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003462 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003463 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003464 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003465 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003466 " | While not properly invalid, you will certainly encounter various problems\n"
3467 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003468 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003469 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003470 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003471
Willy Tarreau1fa31262007-12-03 00:36:16 +01003472 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3473 * We must still support older configurations, so let's find out whether those
3474 * parameters have been set or must be copied from contimeouts.
3475 */
3476 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003477 if (!curproxy->timeout.tarpit ||
3478 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003479 /* tarpit timeout not set. We search in the following order:
3480 * default.tarpit, curr.connect, default.connect.
3481 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003482 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003483 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003484 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003485 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003486 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003487 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003488 }
3489 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003490 (!curproxy->timeout.queue ||
3491 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003492 /* queue timeout not set. We search in the following order:
3493 * default.queue, curr.connect, default.connect.
3494 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003495 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003496 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003497 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003498 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003499 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003500 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003501 }
3502 }
3503
Willy Tarreauf3c69202006-07-09 16:42:34 +02003504 if (curproxy->options & PR_O_SSL3_CHK) {
3505 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3506 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3507 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3508 }
3509
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003510 /* The small pools required for the capture lists */
3511 if (curproxy->nb_req_cap)
3512 curproxy->req_cap_pool = create_pool("ptrcap",
3513 curproxy->nb_req_cap * sizeof(char *),
3514 MEM_F_SHARED);
3515 if (curproxy->nb_rsp_cap)
3516 curproxy->rsp_cap_pool = create_pool("ptrcap",
3517 curproxy->nb_rsp_cap * sizeof(char *),
3518 MEM_F_SHARED);
3519
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003520 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3521 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3522 MEM_F_SHARED);
3523
Willy Tarreau86034312006-12-29 00:10:33 +01003524 /* for backwards compatibility with "listen" instances, if
3525 * fullconn is not set but maxconn is set, then maxconn
3526 * is used.
3527 */
3528 if (!curproxy->fullconn)
3529 curproxy->fullconn = curproxy->maxconn;
3530
Willy Tarreaubaaee002006-06-26 02:48:02 +02003531 /* first, we will invert the servers list order */
3532 newsrv = NULL;
3533 while (curproxy->srv) {
3534 struct server *next;
3535
3536 next = curproxy->srv->next;
3537 curproxy->srv->next = newsrv;
3538 newsrv = curproxy->srv;
3539 if (!next)
3540 break;
3541 curproxy->srv = next;
3542 }
3543
Willy Tarreau20697042007-11-15 23:26:18 +01003544 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003545 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546
Willy Tarreaub625a082007-11-26 01:15:43 +01003547 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003548 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003549 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003550 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3551 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003552 else
3553 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554
3555 if (curproxy->options & PR_O_LOGASAP)
3556 curproxy->to_log &= ~LW_BYTES;
3557
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003559 * ensure that we're not cross-dressing a TCP server into HTTP.
3560 */
3561 newsrv = curproxy->srv;
3562 while (newsrv != NULL) {
3563 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003564 Alert("parsing [%s:%d] : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3565 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003566 goto err;
3567 }
3568 newsrv = newsrv->next;
3569 }
3570
3571 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 * If this server supports a maxconn parameter, it needs a dedicated
3573 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003574 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 */
3576 newsrv = curproxy->srv;
3577 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003578 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 /* Only 'minconn' was specified, or it was higher than or equal
3580 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3581 * this will avoid further useless expensive computations.
3582 */
3583 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003584 } else if (newsrv->maxconn && !newsrv->minconn) {
3585 /* minconn was not specified, so we set it to maxconn */
3586 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003587 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003588 Alert("parsing [%s:%d] : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3589 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003590 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003593 if (newsrv->trackit) {
3594 struct proxy *px;
3595 struct server *srv;
3596 char *pname, *sname;
3597
3598 pname = newsrv->trackit;
3599 sname = strrchr(pname, '/');
3600
3601 if (sname)
3602 *sname++ = '\0';
3603 else {
3604 sname = pname;
3605 pname = NULL;
3606 }
3607
3608 if (pname) {
3609 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3610 if (!px) {
3611 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3612 file, proxy_type_str(curproxy), curproxy->id,
3613 newsrv->id, pname);
3614 return -1;
3615 }
3616 } else
3617 px = curproxy;
3618
3619 srv = findserver(px, sname);
3620 if (!srv) {
3621 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3622 file, proxy_type_str(curproxy), curproxy->id,
3623 newsrv->id, sname);
3624 return -1;
3625 }
3626
3627 if (!(srv->state & SRV_CHECKED)) {
3628 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3629 "tracing as it does not have checks enabled.\n",
3630 file, proxy_type_str(curproxy), curproxy->id,
3631 newsrv->id, px->id, srv->id);
3632 return -1;
3633 }
3634
3635 if (curproxy != px &&
3636 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3637 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3638 "tracing: disable-on-404 option inconsistency.\n",
3639 file, proxy_type_str(curproxy), curproxy->id,
3640 newsrv->id, px->id, srv->id);
3641 return -1;
3642 }
3643
3644 newsrv->tracked = srv;
3645 newsrv->tracknext = srv->tracknext;
3646 srv->tracknext = newsrv;
3647
3648 free(newsrv->trackit);
3649 }
3650
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 newsrv = newsrv->next;
3652 }
3653
Willy Tarreaue6b98942007-10-29 01:09:36 +01003654 /* adjust this proxy's listeners */
3655 listener = curproxy->listen;
3656 while (listener) {
3657 if (curproxy->options & PR_O_TCP_NOLING)
3658 listener->options |= LI_O_NOLINGER;
3659 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003660 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003661 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003662 listener->accept = event_accept;
3663 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003664 listener->handler = process_session;
3665
3666 if (curproxy->mode == PR_MODE_HTTP)
3667 listener->analysers |= AN_REQ_HTTP_HDR;
3668
Willy Tarreaud869b242009-03-15 14:43:58 +01003669 if (curproxy->tcp_req.inspect_delay ||
3670 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003671 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003672
3673 listener = listener->next;
3674 }
3675
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 curproxy = curproxy->next;
3677 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003678
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 if (cfgerr > 0) {
3680 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003681 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003683
3684 /*
3685 * Recount currently required checks.
3686 */
3687
3688 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3689 int optnum;
3690
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003691 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3692 if (curproxy->options & cfg_opts[optnum].val)
3693 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003694
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003695 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3696 if (curproxy->options2 & cfg_opts2[optnum].val)
3697 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003698 }
3699
Willy Tarreaua534fea2008-08-03 12:19:50 +02003700 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003701 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003702 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003703
3704 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003705 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003706 cursection = NULL;
3707 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708}
3709
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003710/*
3711 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3712 * parsing sessions.
3713 */
3714void cfg_register_keywords(struct cfg_kw_list *kwl)
3715{
3716 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3717}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003719/*
3720 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3721 */
3722void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3723{
3724 LIST_DEL(&kwl->list);
3725 LIST_INIT(&kwl->list);
3726}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003727
3728/*
3729 * Local variables:
3730 * c-indent-level: 8
3731 * c-basic-offset: 8
3732 * End:
3733 */