blob: bfcccf2648e8b5eee59a99fdc725abe85bc51b9e [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 Tarreauf7edefa2009-05-10 17:20:05 +0200556 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557
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
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200578 minlvl = 0; /* limit syslog level to this level (emerg) */
579 if (*(args[4])) {
580 minlvl = get_log_level(args[4]);
581 if (level < 0) {
582 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
583 exit(1);
584 }
585 }
586
Robert Tsai81ae1952007-12-05 10:47:29 +0100587 if (args[1][0] == '/') {
588 logsrv.u.addr.sa_family = AF_UNIX;
589 logsrv.u.un = *str2sun(args[1]);
590 } else {
591 logsrv.u.addr.sa_family = AF_INET;
592 logsrv.u.in = *str2sa(args[1]);
593 if (!logsrv.u.in.sin_port)
594 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596
597 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100598 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 global.logfac1 = facility;
600 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200601 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100604 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 global.logfac2 = facility;
606 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200607 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 else {
610 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
611 return -1;
612 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200613 }
614 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
615 if (global.spread_checks != 0) {
616 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
617 return 0;
618 }
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
621 return -1;
622 }
623 global.spread_checks = atol(args[1]);
624 if (global.spread_checks < 0 || global.spread_checks > 50) {
625 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
626 return -1;
627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200630 struct cfg_kw_list *kwl;
631 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200632 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200633
634 list_for_each_entry(kwl, &cfg_keywords.list, list) {
635 for (index = 0; kwl->kw[index].kw != NULL; index++) {
636 if (kwl->kw[index].section != CFG_GLOBAL)
637 continue;
638 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
639 /* prepare error message just in case */
640 snprintf(trash, sizeof(trash),
641 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200642 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
643 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200644 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
645 return -1;
646 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200647 else if (rc > 0) {
648 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
649 return 0;
650 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200651 return 0;
652 }
653 }
654 }
655
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
657 return -1;
658 }
659 return 0;
660}
661
662
663static void init_default_instance()
664{
665 memset(&defproxy, 0, sizeof(defproxy));
666 defproxy.mode = PR_MODE_TCP;
667 defproxy.state = PR_STNEW;
668 defproxy.maxconn = cfg_maxpconn;
669 defproxy.conn_retries = CONN_RETRIES;
670 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200671
672 LIST_INIT(&defproxy.pendconns);
673 LIST_INIT(&defproxy.acl);
674 LIST_INIT(&defproxy.block_cond);
675 LIST_INIT(&defproxy.mon_fail_cond);
676 LIST_INIT(&defproxy.switching_rules);
677
Willy Tarreau3a70f942008-02-15 11:15:34 +0100678 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679}
680
681/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100682 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
683 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100685int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686{
687 static struct proxy *curproxy = NULL;
688 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200689 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100690 int rc;
691 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692
Willy Tarreau977b8e42006-12-29 14:19:17 +0100693 if (!strcmp(args[0], "listen"))
694 rc = PR_CAP_LISTEN;
695 else if (!strcmp(args[0], "frontend"))
696 rc = PR_CAP_FE | PR_CAP_RS;
697 else if (!strcmp(args[0], "backend"))
698 rc = PR_CAP_BE | PR_CAP_RS;
699 else if (!strcmp(args[0], "ruleset"))
700 rc = PR_CAP_RS;
701 else
702 rc = PR_CAP_NONE;
703
704 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 if (!*args[1]) {
706 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
707 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
708 file, linenum, args[0]);
709 return -1;
710 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200711
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100712 err = invalid_char(args[1]);
713 if (err) {
714 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
715 file, linenum, *err, args[0], args[1]);
716 return -1;
717 }
718
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200719 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
720 /*
721 * If there are two proxies with the same name only following
722 * combinations are allowed:
723 *
724 * listen backend frontend ruleset
725 * listen - - - -
726 * backend - - OK -
727 * frontend - OK - -
728 * ruleset - - - -
729 */
730
731 if (!strcmp(curproxy->id, args[1]) &&
732 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
733 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100734 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
735 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200736 }
737 }
738
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
740 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
741 return -1;
742 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100743
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 curproxy->next = proxy;
745 proxy = curproxy;
746 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200747 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200748 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200749 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100750 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200751 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200752 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753
Willy Tarreauee991362007-05-14 14:37:50 +0200754 /* Timeouts are defined as -1, so we cannot use the zeroed area
755 * as a default value.
756 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100757 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200758
759 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100761 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762
763 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100764 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 curproxy->listen = str2listener(args[2], curproxy->listen);
766 if (!curproxy->listen)
767 return -1;
768 global.maxsock++;
769 }
770
771 /* set default values */
772 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100774 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100775 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100776 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200777 curproxy->except_net = defproxy.except_net;
778 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200779 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200780 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200782 if (defproxy.fwdfor_hdr_len) {
783 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
784 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
785 }
786
Willy Tarreau977b8e42006-12-29 14:19:17 +0100787 if (curproxy->cap & PR_CAP_FE) {
788 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100789 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200790 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100791
792 /* initialize error relocations */
793 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
794 if (defproxy.errmsg[rc].str)
795 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
796 }
797
798 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800
Willy Tarreau977b8e42006-12-29 14:19:17 +0100801 if (curproxy->cap & PR_CAP_BE) {
802 curproxy->fullconn = defproxy.fullconn;
803 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805 if (defproxy.check_req)
806 curproxy->check_req = strdup(defproxy.check_req);
807 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808
Willy Tarreau977b8e42006-12-29 14:19:17 +0100809 if (defproxy.cookie_name)
810 curproxy->cookie_name = strdup(defproxy.cookie_name);
811 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100812
813 if (defproxy.url_param_name)
814 curproxy->url_param_name = strdup(defproxy.url_param_name);
815 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100816
Benoitaffb4812009-03-25 13:02:10 +0100817 if (defproxy.hh_name)
818 curproxy->hh_name = strdup(defproxy.hh_name);
819 curproxy->hh_len = defproxy.hh_len;
820 curproxy->hh_match_domain = defproxy.hh_match_domain;
821
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100822 if (defproxy.iface_name)
823 curproxy->iface_name = strdup(defproxy.iface_name);
824 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826
Willy Tarreau977b8e42006-12-29 14:19:17 +0100827 if (curproxy->cap & PR_CAP_RS) {
828 if (defproxy.capture_name)
829 curproxy->capture_name = strdup(defproxy.capture_name);
830 curproxy->capture_namelen = defproxy.capture_namelen;
831 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833
Willy Tarreau977b8e42006-12-29 14:19:17 +0100834 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100835 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100836 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100837 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100838 curproxy->uri_auth = defproxy.uri_auth;
839 curproxy->mon_net = defproxy.mon_net;
840 curproxy->mon_mask = defproxy.mon_mask;
841 if (defproxy.monitor_uri)
842 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
843 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100844 if (defproxy.defbe.name)
845 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100846 }
847
848 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100849 curproxy->timeout.connect = defproxy.timeout.connect;
850 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100851 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100852 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100853 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100854 curproxy->source_addr = defproxy.source_addr;
855 }
856
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 curproxy->mode = defproxy.mode;
858 curproxy->logfac1 = defproxy.logfac1;
859 curproxy->logsrv1 = defproxy.logsrv1;
860 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200861 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 curproxy->logfac2 = defproxy.logfac2;
863 curproxy->logsrv2 = defproxy.logsrv2;
864 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200865 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100867 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
868 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200869
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 return 0;
871 }
872 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
873 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100874 /* FIXME-20070101: we should do this too at the end of the
875 * config parsing to free all default values.
876 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200877 free(defproxy.check_req);
878 free(defproxy.cookie_name);
879 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100880 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200881 free(defproxy.capture_name);
882 free(defproxy.monitor_uri);
883 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100884 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200885 free(defproxy.fwdfor_hdr_name);
886 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100887
Willy Tarreaua534fea2008-08-03 12:19:50 +0200888 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
889 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100890
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 /* we cannot free uri_auth because it might already be used */
892 init_default_instance();
893 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100894 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 return 0;
896 }
897 else if (curproxy == NULL) {
898 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
899 return -1;
900 }
901
Willy Tarreau977b8e42006-12-29 14:19:17 +0100902
903 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100905 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100906 int cur_arg;
907
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 if (curproxy == &defproxy) {
909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
910 return -1;
911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100912 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
913 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914
915 if (strchr(args[1], ':') == NULL) {
916 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
917 file, linenum, args[0]);
918 return -1;
919 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100920
921 last_listen = curproxy->listen;
922 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 if (!curproxy->listen)
924 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100925
926 cur_arg = 2;
927 while (*(args[cur_arg])) {
928 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
929#ifdef SO_BINDTODEVICE
930 struct listener *l;
931
932 if (!*args[cur_arg + 1]) {
933 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
934 file, linenum, args[0]);
935 return -1;
936 }
937
938 for (l = curproxy->listen; l != last_listen; l = l->next)
939 l->interface = strdup(args[cur_arg + 1]);
940
941 global.last_checks |= LSTCHK_NETADM;
942
943 cur_arg += 2;
944 continue;
945#else
946 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
947 file, linenum, args[0], args[cur_arg]);
948 return -1;
949#endif
950 }
951 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100952#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100953 struct listener *l;
954
955 for (l = curproxy->listen; l != last_listen; l = l->next)
956 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100957
958 cur_arg ++;
959 continue;
960#else
961 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
962 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100963 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100964#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100965 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100966 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100967 file, linenum, args[0]);
968 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 global.maxsock++;
971 return 0;
972 }
973 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
974 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
975 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
976 file, linenum, args[0]);
977 return -1;
978 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
980 return 0;
981
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 /* flush useless bits */
983 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
984 return 0;
985 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200986 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100987 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
988 return 0;
989
Willy Tarreau1c47f852006-07-09 08:22:27 +0200990 if (!*args[1]) {
991 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
992 file, linenum, args[0]);
993 return -1;
994 }
995
Willy Tarreaua534fea2008-08-03 12:19:50 +0200996 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100997 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200998 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100999 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001000 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1001
1002 return 0;
1003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1005 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1006 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1007 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1008 else {
1009 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
1010 return -1;
1011 }
1012 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001013 else if (!strcmp(args[0], "id")) {
1014 struct proxy *target;
1015
1016 if (curproxy == &defproxy) {
1017 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1018 file, linenum, args[0]);
1019 return -1;
1020 }
1021
1022 if (!*args[1]) {
1023 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1024 file, linenum, args[0]);
1025 return -1;
1026 }
1027
1028 curproxy->uuid = atol(args[1]);
1029
1030 if (curproxy->uuid < 1001) {
1031 Alert("parsing [%s:%d]: custom id has to be > 1000",
1032 file, linenum);
1033 return -1;
1034 }
1035
1036 for (target = proxy; target; target = target->next)
1037 if (curproxy != target && curproxy->uuid == target->uuid) {
1038 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1039 file, linenum, curproxy->id, target->id);
1040 return -1;
1041 }
1042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1044 curproxy->state = PR_STSTOPPED;
1045 }
1046 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1047 curproxy->state = PR_STNEW;
1048 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001049 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1050 int cur_arg = 1;
1051 unsigned int set = 0;
1052
1053 while (*args[cur_arg]) {
1054 int u;
1055 if (strcmp(args[cur_arg], "all") == 0) {
1056 set = 0;
1057 break;
1058 }
1059 else if (strcmp(args[cur_arg], "odd") == 0) {
1060 set |= 0x55555555;
1061 }
1062 else if (strcmp(args[cur_arg], "even") == 0) {
1063 set |= 0xAAAAAAAA;
1064 }
1065 else {
1066 u = str2uic(args[cur_arg]);
1067 if (u < 1 || u > 32) {
1068 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1069 file, linenum, args[0]);
1070 return -1;
1071 }
1072 if (u > global.nbproc) {
1073 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1074 file, linenum, args[0]);
1075 }
1076 set |= 1 << (u - 1);
1077 }
1078 cur_arg++;
1079 }
1080 curproxy->bind_proc = set;
1081 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001082 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001083 if (curproxy == &defproxy) {
1084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1085 return -1;
1086 }
1087
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001088 err = invalid_char(args[1]);
1089 if (err) {
1090 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1091 file, linenum, *err, args[1]);
1092 return -1;
1093 }
1094
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001095 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1096 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1097 file, linenum, args[1]);
1098 return -1;
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1102 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103
Willy Tarreau977b8e42006-12-29 14:19:17 +01001104 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1105 return 0;
1106
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1109 file, linenum, args[0]);
1110 return -1;
1111 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001112
1113 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 curproxy->cookie_name = strdup(args[1]);
1115 curproxy->cookie_len = strlen(curproxy->cookie_name);
1116
1117 cur_arg = 2;
1118 while (*(args[cur_arg])) {
1119 if (!strcmp(args[cur_arg], "rewrite")) {
1120 curproxy->options |= PR_O_COOK_RW;
1121 }
1122 else if (!strcmp(args[cur_arg], "indirect")) {
1123 curproxy->options |= PR_O_COOK_IND;
1124 }
1125 else if (!strcmp(args[cur_arg], "insert")) {
1126 curproxy->options |= PR_O_COOK_INS;
1127 }
1128 else if (!strcmp(args[cur_arg], "nocache")) {
1129 curproxy->options |= PR_O_COOK_NOC;
1130 }
1131 else if (!strcmp(args[cur_arg], "postonly")) {
1132 curproxy->options |= PR_O_COOK_POST;
1133 }
1134 else if (!strcmp(args[cur_arg], "prefix")) {
1135 curproxy->options |= PR_O_COOK_PFX;
1136 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001137 else if (!strcmp(args[cur_arg], "domain")) {
1138 if (!*args[cur_arg + 1]) {
1139 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1140 file, linenum, args[cur_arg]);
1141 return -1;
1142 }
1143
1144 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1145 /* rfc2109, 4.3.2 Rejecting Cookies */
1146 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1147 " dots or does not start with a dot.\n",
1148 file, linenum, args[cur_arg + 1]);
1149 return -1;
1150 }
1151
1152 err = invalid_domainchar(args[cur_arg + 1]);
1153 if (err) {
1154 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1155 file, linenum, *err, args[cur_arg + 1]);
1156 return -1;
1157 }
1158
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001159 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001160 cur_arg++;
1161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001163 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 file, linenum, args[0]);
1165 return -1;
1166 }
1167 cur_arg++;
1168 }
1169 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1170 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1171 file, linenum);
1172 return -1;
1173 }
1174
1175 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1176 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1177 file, linenum);
1178 return -1;
1179 }
1180 }/* end else if (!strcmp(args[0], "cookie")) */
1181 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182
Willy Tarreau977b8e42006-12-29 14:19:17 +01001183 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1184 return 0;
1185
Willy Tarreaubaaee002006-06-26 02:48:02 +02001186 if (*(args[5]) == 0) {
1187 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1188 file, linenum, args[0]);
1189 return -1;
1190 }
1191 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001192 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 curproxy->appsession_name = strdup(args[1]);
1194 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1195 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001196 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1197 if (err) {
1198 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1199 file, linenum, *err, args[0]);
1200 return -1;
1201 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001202 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001203
Willy Tarreau51041c72007-09-09 21:56:53 +02001204 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 return -1;
1207 }
1208 } /* Url App Session */
1209 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001210 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1211 return 0;
1212
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 if (*(args[4]) == 0) {
1215 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1216 file, linenum, args[0]);
1217 return -1;
1218 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001219 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 curproxy->capture_name = strdup(args[2]);
1221 curproxy->capture_namelen = strlen(curproxy->capture_name);
1222 curproxy->capture_len = atol(args[4]);
1223 if (curproxy->capture_len >= CAPTURE_LEN) {
1224 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1225 file, linenum, CAPTURE_LEN - 1);
1226 curproxy->capture_len = CAPTURE_LEN - 1;
1227 }
1228 curproxy->to_log |= LW_COOKIE;
1229 }
1230 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1231 struct cap_hdr *hdr;
1232
1233 if (curproxy == &defproxy) {
1234 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1235 return -1;
1236 }
1237
1238 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1239 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1240 file, linenum, args[0], args[1]);
1241 return -1;
1242 }
1243
1244 hdr = calloc(sizeof(struct cap_hdr), 1);
1245 hdr->next = curproxy->req_cap;
1246 hdr->name = strdup(args[3]);
1247 hdr->namelen = strlen(args[3]);
1248 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001249 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 hdr->index = curproxy->nb_req_cap++;
1251 curproxy->req_cap = hdr;
1252 curproxy->to_log |= LW_REQHDR;
1253 }
1254 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1255 struct cap_hdr *hdr;
1256
1257 if (curproxy == &defproxy) {
1258 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1259 return -1;
1260 }
1261
1262 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1263 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1264 file, linenum, args[0], args[1]);
1265 return -1;
1266 }
1267 hdr = calloc(sizeof(struct cap_hdr), 1);
1268 hdr->next = curproxy->rsp_cap;
1269 hdr->name = strdup(args[3]);
1270 hdr->namelen = strlen(args[3]);
1271 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001272 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001273 hdr->index = curproxy->nb_rsp_cap++;
1274 curproxy->rsp_cap = hdr;
1275 curproxy->to_log |= LW_RSPHDR;
1276 }
1277 else {
1278 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1279 file, linenum, args[0]);
1280 return -1;
1281 }
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1285 return 0;
1286
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 if (*(args[1]) == 0) {
1288 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1289 file, linenum, args[0]);
1290 return -1;
1291 }
1292 curproxy->conn_retries = atol(args[1]);
1293 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001294 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1295 int pol = ACL_COND_NONE;
1296 struct acl_cond *cond;
1297
Willy Tarreaub099aca2008-10-12 17:26:37 +02001298 if (curproxy == &defproxy) {
1299 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1300 return -1;
1301 }
1302
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001303 if (!strcmp(args[1], "if"))
1304 pol = ACL_COND_IF;
1305 else if (!strcmp(args[1], "unless"))
1306 pol = ACL_COND_UNLESS;
1307
1308 if (pol == ACL_COND_NONE) {
1309 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1310 file, linenum, args[0]);
1311 return -1;
1312 }
1313
1314 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1315 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1316 file, linenum);
1317 return -1;
1318 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001319 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001320 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001321 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001322 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001323 else if (!strcmp(args[0], "redirect")) {
1324 int pol = ACL_COND_NONE;
1325 struct acl_cond *cond;
1326 struct redirect_rule *rule;
1327 int cur_arg;
1328 int type = REDIRECT_TYPE_NONE;
1329 int code = 302;
1330 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001331 char *cookie = NULL;
1332 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001333 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001334
1335 cur_arg = 1;
1336 while (*(args[cur_arg])) {
1337 if (!strcmp(args[cur_arg], "location")) {
1338 if (!*args[cur_arg + 1]) {
1339 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1340 file, linenum, args[0], args[cur_arg]);
1341 return -1;
1342 }
1343
1344 type = REDIRECT_TYPE_LOCATION;
1345 cur_arg++;
1346 destination = args[cur_arg];
1347 }
1348 else if (!strcmp(args[cur_arg], "prefix")) {
1349 if (!*args[cur_arg + 1]) {
1350 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1351 file, linenum, args[0], args[cur_arg]);
1352 return -1;
1353 }
1354
1355 type = REDIRECT_TYPE_PREFIX;
1356 cur_arg++;
1357 destination = args[cur_arg];
1358 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001359 else if (!strcmp(args[cur_arg], "set-cookie")) {
1360 if (!*args[cur_arg + 1]) {
1361 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1362 file, linenum, args[0], args[cur_arg]);
1363 return -1;
1364 }
1365
1366 cur_arg++;
1367 cookie = args[cur_arg];
1368 cookie_set = 1;
1369 }
1370 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1371 if (!*args[cur_arg + 1]) {
1372 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1373 file, linenum, args[0], args[cur_arg]);
1374 return -1;
1375 }
1376
1377 cur_arg++;
1378 cookie = args[cur_arg];
1379 cookie_set = 0;
1380 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001381 else if (!strcmp(args[cur_arg],"code")) {
1382 if (!*args[cur_arg + 1]) {
1383 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1384 file, linenum, args[0]);
1385 return -1;
1386 }
1387 cur_arg++;
1388 code = atol(args[cur_arg]);
1389 if (code < 301 || code > 303) {
1390 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1391 file, linenum, args[0], code);
1392 return -1;
1393 }
1394 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001395 else if (!strcmp(args[cur_arg],"drop-query")) {
1396 flags |= REDIRECT_FLAG_DROP_QS;
1397 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001398 else if (!strcmp(args[cur_arg], "if")) {
1399 pol = ACL_COND_IF;
1400 cur_arg++;
1401 break;
1402 }
1403 else if (!strcmp(args[cur_arg], "unless")) {
1404 pol = ACL_COND_UNLESS;
1405 cur_arg++;
1406 break;
1407 }
1408 else {
1409 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1410 file, linenum, args[0], args[cur_arg]);
1411 return -1;
1412 }
1413 cur_arg++;
1414 }
1415
1416 if (type == REDIRECT_TYPE_NONE) {
1417 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1418 file, linenum, args[0]);
1419 return -1;
1420 }
1421
1422 if (pol == ACL_COND_NONE) {
1423 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1424 file, linenum, args[0]);
1425 return -1;
1426 }
1427
1428 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001429 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001430 file, linenum, args[0]);
1431 return -1;
1432 }
1433
Willy Tarreaua9802632008-07-25 19:13:19 +02001434 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001435 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1436 rule->cond = cond;
1437 rule->rdr_str = strdup(destination);
1438 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001439 if (cookie) {
1440 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1441 * a clear consists in appending "; Max-Age=0" at the end.
1442 */
1443 rule->cookie_len = strlen(cookie);
1444 if (cookie_set)
1445 rule->cookie_str = strdup(cookie);
1446 else {
1447 rule->cookie_str = malloc(rule->cookie_len + 12);
1448 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1449 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1450 rule->cookie_len += 11;
1451 }
1452 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001453 rule->type = type;
1454 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001455 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001456 LIST_INIT(&rule->list);
1457 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001458 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001459 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001460 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001461 int pol = ACL_COND_NONE;
1462 struct acl_cond *cond;
1463 struct switching_rule *rule;
1464
Willy Tarreaub099aca2008-10-12 17:26:37 +02001465 if (curproxy == &defproxy) {
1466 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1467 return -1;
1468 }
1469
Willy Tarreau55ea7572007-06-17 19:56:27 +02001470 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1471 return 0;
1472
1473 if (*(args[1]) == 0) {
1474 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1475 return -1;
1476 }
1477
1478 if (!strcmp(args[2], "if"))
1479 pol = ACL_COND_IF;
1480 else if (!strcmp(args[2], "unless"))
1481 pol = ACL_COND_UNLESS;
1482
1483 if (pol == ACL_COND_NONE) {
1484 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1485 file, linenum, args[0]);
1486 return -1;
1487 }
1488
1489 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001490 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001491 file, linenum);
1492 return -1;
1493 }
1494
Willy Tarreaua9802632008-07-25 19:13:19 +02001495 cond->line = linenum;
1496 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001497 struct acl *acl;
1498 const char *name;
1499
1500 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1501 name = acl ? acl->name : "(unknown)";
1502 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1503 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001504 }
1505
Willy Tarreau55ea7572007-06-17 19:56:27 +02001506 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1507 rule->cond = cond;
1508 rule->be.name = strdup(args[1]);
1509 LIST_INIT(&rule->list);
1510 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1514 return 0;
1515
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1517 curproxy->uri_auth = NULL; /* we must detach from the default config */
1518
1519 if (*(args[1]) == 0) {
1520 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1521 return -1;
1522 } else if (!strcmp(args[1], "uri")) {
1523 if (*(args[2]) == 0) {
1524 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1525 return -1;
1526 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1527 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1528 return -1;
1529 }
1530 } else if (!strcmp(args[1], "realm")) {
1531 if (*(args[2]) == 0) {
1532 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1533 return -1;
1534 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1535 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1536 return -1;
1537 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001538 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001539 unsigned interval;
1540
1541 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1542 if (err) {
1543 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1544 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001545 return -1;
1546 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1547 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1548 return -1;
1549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 } else if (!strcmp(args[1], "auth")) {
1551 if (*(args[2]) == 0) {
1552 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1553 return -1;
1554 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1556 return -1;
1557 }
1558 } else if (!strcmp(args[1], "scope")) {
1559 if (*(args[2]) == 0) {
1560 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1561 return -1;
1562 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1563 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1564 return -1;
1565 }
1566 } else if (!strcmp(args[1], "enable")) {
1567 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1569 return -1;
1570 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001571 } else if (!strcmp(args[1], "hide-version")) {
1572 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1574 return -1;
1575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001577 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 file, linenum, args[0]);
1579 return -1;
1580 }
1581 }
1582 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001583 int optnum;
1584
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001585 if (*(args[1]) == '\0') {
1586 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1587 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 return -1;
1589 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001590
1591 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1592 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1593 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1594 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001595
1596 if (!inv)
1597 curproxy->options |= cfg_opts[optnum].val;
1598 else
1599 curproxy->options &= ~cfg_opts[optnum].val;
1600
Willy Tarreau13943ab2006-12-31 00:24:10 +01001601 return 0;
1602 }
1603 }
1604
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001605 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1606 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1607 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1608 return 0;
1609
1610 if (!inv)
1611 curproxy->options2 |= cfg_opts2[optnum].val;
1612 else
1613 curproxy->options2 &= ~cfg_opts2[optnum].val;
1614
1615 return 0;
1616 }
1617 }
1618
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001619 if (inv) {
1620 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1621 file, linenum, args[1]);
1622 return -1;
1623 }
1624
Willy Tarreau13943ab2006-12-31 00:24:10 +01001625 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 /* generate a complete HTTP log */
1627 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1628 else if (!strcmp(args[1], "tcplog"))
1629 /* generate a detailed TCP log */
1630 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 else if (!strcmp(args[1], "tcpka")) {
1632 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001633 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1634 return 0;
1635
1636 if (curproxy->cap & PR_CAP_FE)
1637 curproxy->options |= PR_O_TCP_CLI_KA;
1638 if (curproxy->cap & PR_CAP_BE)
1639 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
1641 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001642 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1643 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001645 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001646 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001647 curproxy->options &= ~PR_O_SMTP_CHK;
1648 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[2]) { /* no argument */
1650 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1651 curproxy->check_len = strlen(DEF_CHECK_REQ);
1652 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001653 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 curproxy->check_req = (char *)malloc(reqlen);
1655 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1656 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1657 } else { /* more arguments : METHOD URI [HTTP_VER] */
1658 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1659 if (*args[4])
1660 reqlen += strlen(args[4]);
1661 else
1662 reqlen += strlen("HTTP/1.0");
1663
1664 curproxy->check_req = (char *)malloc(reqlen);
1665 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1666 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1667 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001668 }
1669 else if (!strcmp(args[1], "ssl-hello-chk")) {
1670 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1672 return 0;
1673
Willy Tarreaua534fea2008-08-03 12:19:50 +02001674 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001675 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001676 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001677 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 }
Willy Tarreau23677902007-05-08 23:50:35 +02001679 else if (!strcmp(args[1], "smtpchk")) {
1680 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001681 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001682 curproxy->options &= ~PR_O_HTTP_CHK;
1683 curproxy->options &= ~PR_O_SSL3_CHK;
1684 curproxy->options |= PR_O_SMTP_CHK;
1685
1686 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1687 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1688 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1689 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1690 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1691 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1692 curproxy->check_req = (char *)malloc(reqlen);
1693 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1694 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1695 } else {
1696 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1697 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1698 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1699 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1700 }
1701 }
1702 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001703 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001704 int cur_arg;
1705
1706 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1707 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001708 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001709
1710 curproxy->options |= PR_O_FWDFOR;
1711
1712 free(curproxy->fwdfor_hdr_name);
1713 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1714 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1715
1716 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1717 cur_arg = 2;
1718 while (*(args[cur_arg])) {
1719 if (!strcmp(args[cur_arg], "except")) {
1720 /* suboption except - needs additional argument for it */
1721 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1722 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1723 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001724 return -1;
1725 }
1726 /* flush useless bits */
1727 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001728 cur_arg += 2;
1729 } else if (!strcmp(args[cur_arg], "header")) {
1730 /* suboption header - needs additional argument for it */
1731 if (*(args[cur_arg+1]) == 0) {
1732 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1733 file, linenum, args[0], args[1], args[cur_arg]);
1734 return -1;
1735 }
1736 free(curproxy->fwdfor_hdr_name);
1737 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1738 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1739 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001740 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001741 /* unknown suboption - catchall */
1742 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1743 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001744 return -1;
1745 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001746 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001747 }
Maik Broemme2850cb42009-04-17 18:53:21 +02001748 else if (!strcmp(args[1], "originalto")) {
1749 int cur_arg;
1750
1751 /* insert x-original-to field, but not for the IP address listed as an except.
1752 * set default options (ie: bitfield, header name, etc)
1753 */
1754
1755 curproxy->options |= PR_O_ORGTO;
1756
1757 free(curproxy->orgto_hdr_name);
1758 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
1759 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
1760
1761 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1762 cur_arg = 2;
1763 while (*(args[cur_arg])) {
1764 if (!strcmp(args[cur_arg], "except")) {
1765 /* suboption except - needs additional argument for it */
1766 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
1767 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1768 file, linenum, args[0], args[1], args[cur_arg]);
1769 return -1;
1770 }
1771 /* flush useless bits */
1772 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
1773 cur_arg += 2;
1774 } else if (!strcmp(args[cur_arg], "header")) {
1775 /* suboption header - needs additional argument for it */
1776 if (*(args[cur_arg+1]) == 0) {
1777 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1778 file, linenum, args[0], args[1], args[cur_arg]);
1779 return -1;
1780 }
1781 free(curproxy->orgto_hdr_name);
1782 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
1783 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
1784 cur_arg += 2;
1785 } else {
1786 /* unknown suboption - catchall */
1787 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1788 file, linenum, args[0], args[1]);
1789 return -1;
1790 }
1791 } /* end while loop */
1792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 else {
1794 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1795 return -1;
1796 }
1797 return 0;
1798 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001799 else if (!strcmp(args[0], "default_backend")) {
1800 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1801 return 0;
1802
1803 if (*(args[1]) == 0) {
1804 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1805 return -1;
1806 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001807 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001808 curproxy->defbe.name = strdup(args[1]);
1809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1812 return 0;
1813
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001814 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1815 file, linenum, args[0]);
1816
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817 /* enable reconnections to dispatch */
1818 curproxy->options |= PR_O_REDISP;
1819 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001820 else if (!strcmp(args[0], "http-check")) {
1821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1822 return 0;
1823
1824 if (strcmp(args[1], "disable-on-404") == 0) {
1825 /* enable a graceful server shutdown on an HTTP 404 response */
1826 curproxy->options |= PR_O_DISABLE404;
1827 }
1828 else {
1829 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1830 return -1;
1831 }
1832 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001833 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001834 if (curproxy == &defproxy) {
1835 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1836 return -1;
1837 }
1838
Willy Tarreaub80c2302007-11-30 20:51:32 +01001839 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1840 return 0;
1841
1842 if (strcmp(args[1], "fail") == 0) {
1843 /* add a condition to fail monitor requests */
1844 int pol = ACL_COND_NONE;
1845 struct acl_cond *cond;
1846
1847 if (!strcmp(args[2], "if"))
1848 pol = ACL_COND_IF;
1849 else if (!strcmp(args[2], "unless"))
1850 pol = ACL_COND_UNLESS;
1851
1852 if (pol == ACL_COND_NONE) {
1853 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1854 file, linenum, args[0], args[1]);
1855 return -1;
1856 }
1857
1858 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1859 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1860 file, linenum, args[0], args[1]);
1861 return -1;
1862 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001863 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001864 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1865 }
1866 else {
1867 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1868 return -1;
1869 }
1870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871#ifdef TPROXY
1872 else if (!strcmp(args[0], "transparent")) {
1873 /* enable transparent proxy connections */
1874 curproxy->options |= PR_O_TRANSP;
1875 }
1876#endif
1877 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001878 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1879 return 0;
1880
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 if (*(args[1]) == 0) {
1882 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1883 return -1;
1884 }
1885 curproxy->maxconn = atol(args[1]);
1886 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001887 else if (!strcmp(args[0], "backlog")) { /* backlog */
1888 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1889 return 0;
1890
1891 if (*(args[1]) == 0) {
1892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1893 return -1;
1894 }
1895 curproxy->backlog = atol(args[1]);
1896 }
Willy Tarreau86034312006-12-29 00:10:33 +01001897 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1899 return 0;
1900
Willy Tarreau86034312006-12-29 00:10:33 +01001901 if (*(args[1]) == 0) {
1902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1903 return -1;
1904 }
1905 curproxy->fullconn = atol(args[1]);
1906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1908 if (*(args[1]) == 0) {
1909 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1910 return -1;
1911 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001912 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1913 if (err) {
1914 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1915 file, linenum, *err);
1916 return -1;
1917 }
1918 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 }
1920 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1921 if (curproxy == &defproxy) {
1922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1923 return -1;
1924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1926 return 0;
1927
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 if (strchr(args[1], ':') == NULL) {
1929 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1930 return -1;
1931 }
1932 curproxy->dispatch_addr = *str2sa(args[1]);
1933 }
1934 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1936 return 0;
1937
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001938 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001939 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1940 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1941 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
1944 else if (!strcmp(args[0], "server")) { /* server address */
1945 int cur_arg;
1946 char *rport;
1947 char *raddr;
1948 short realport;
1949 int do_check;
1950
1951 if (curproxy == &defproxy) {
1952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1953 return -1;
1954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1956 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957
1958 if (!*args[2]) {
1959 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1960 file, linenum, args[0]);
1961 return -1;
1962 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001963
1964 err = invalid_char(args[1]);
1965 if (err) {
1966 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1967 file, linenum, *err, args[1]);
1968 return -1;
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1972 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1973 return -1;
1974 }
1975
1976 /* the servers are linked backwards first */
1977 newsrv->next = curproxy->srv;
1978 curproxy->srv = newsrv;
1979 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001980 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981
1982 LIST_INIT(&newsrv->pendconns);
1983 do_check = 0;
1984 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001985 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 newsrv->id = strdup(args[1]);
1987
1988 /* several ways to check the port component :
1989 * - IP => port=+0, relative
1990 * - IP: => port=+0, relative
1991 * - IP:N => port=N, absolute
1992 * - IP:+N => port=+N, relative
1993 * - IP:-N => port=-N, relative
1994 */
1995 raddr = strdup(args[2]);
1996 rport = strchr(raddr, ':');
1997 if (rport) {
1998 *rport++ = 0;
1999 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002000 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 newsrv->state |= SRV_MAPPORTS;
2002 } else {
2003 realport = 0;
2004 newsrv->state |= SRV_MAPPORTS;
2005 }
2006
2007 newsrv->addr = *str2sa(raddr);
2008 newsrv->addr.sin_port = htons(realport);
2009 free(raddr);
2010
2011 newsrv->curfd = -1; /* no health-check in progress */
2012 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002013 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2014 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 newsrv->rise = DEF_RISETIME;
2016 newsrv->fall = DEF_FALLTIME;
2017 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002018 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002019 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002020 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002021
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 cur_arg = 3;
2023 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002024 if (!strcmp(args[cur_arg], "id")) {
2025 struct server *target;
2026
2027 if (!*args[cur_arg + 1]) {
2028 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2029 file, linenum, args[cur_arg]);
2030 return -1;
2031 }
2032
2033 newsrv->puid = atol(args[cur_arg + 1]);
2034
2035 if (newsrv->puid< 1001) {
2036 Alert("parsing [%s:%d]: custom id has to be > 1000",
2037 file, linenum);
2038 return -1;
2039 }
2040
2041 for (target = proxy->srv; target; target = target->next)
2042 if (newsrv != target && newsrv->puid == target->puid) {
2043 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2044 file, linenum, newsrv->id, target->id);
2045 return -1;
2046 }
2047 cur_arg += 2;
2048 }
2049 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 newsrv->cookie = strdup(args[cur_arg + 1]);
2051 newsrv->cklen = strlen(args[cur_arg + 1]);
2052 cur_arg += 2;
2053 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002054 else if (!strcmp(args[cur_arg], "redir")) {
2055 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2056 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2057 cur_arg += 2;
2058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 else if (!strcmp(args[cur_arg], "rise")) {
2060 newsrv->rise = atol(args[cur_arg + 1]);
2061 newsrv->health = newsrv->rise;
2062 cur_arg += 2;
2063 }
2064 else if (!strcmp(args[cur_arg], "fall")) {
2065 newsrv->fall = atol(args[cur_arg + 1]);
2066 cur_arg += 2;
2067 }
2068 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002069 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2070 if (err) {
2071 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2072 file, linenum, *err, newsrv->id);
2073 return -1;
2074 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002075 if (val <= 0) {
2076 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2077 file, linenum, val, args[cur_arg], newsrv->id);
2078 return -1;
2079 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002080 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 cur_arg += 2;
2082 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002083 else if (!strcmp(args[cur_arg], "fastinter")) {
2084 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2085 if (err) {
2086 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2087 file, linenum, *err, newsrv->id);
2088 return -1;
2089 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002090 if (val <= 0) {
2091 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2092 file, linenum, val, args[cur_arg], newsrv->id);
2093 return -1;
2094 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002095 newsrv->fastinter = val;
2096 cur_arg += 2;
2097 }
2098 else if (!strcmp(args[cur_arg], "downinter")) {
2099 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2100 if (err) {
2101 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2102 file, linenum, *err, newsrv->id);
2103 return -1;
2104 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002105 if (val <= 0) {
2106 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2107 file, linenum, val, args[cur_arg], newsrv->id);
2108 return -1;
2109 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002110 newsrv->downinter = val;
2111 cur_arg += 2;
2112 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002113 else if (!strcmp(args[cur_arg], "addr")) {
2114 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002115 cur_arg += 2;
2116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 else if (!strcmp(args[cur_arg], "port")) {
2118 newsrv->check_port = atol(args[cur_arg + 1]);
2119 cur_arg += 2;
2120 }
2121 else if (!strcmp(args[cur_arg], "backup")) {
2122 newsrv->state |= SRV_BACKUP;
2123 cur_arg ++;
2124 }
2125 else if (!strcmp(args[cur_arg], "weight")) {
2126 int w;
2127 w = atol(args[cur_arg + 1]);
2128 if (w < 1 || w > 256) {
2129 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
2130 file, linenum, newsrv->id, w);
2131 return -1;
2132 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002133 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 cur_arg += 2;
2135 }
2136 else if (!strcmp(args[cur_arg], "minconn")) {
2137 newsrv->minconn = atol(args[cur_arg + 1]);
2138 cur_arg += 2;
2139 }
2140 else if (!strcmp(args[cur_arg], "maxconn")) {
2141 newsrv->maxconn = atol(args[cur_arg + 1]);
2142 cur_arg += 2;
2143 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002144 else if (!strcmp(args[cur_arg], "maxqueue")) {
2145 newsrv->maxqueue = atol(args[cur_arg + 1]);
2146 cur_arg += 2;
2147 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002148 else if (!strcmp(args[cur_arg], "slowstart")) {
2149 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002150 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002151 if (err) {
2152 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2153 file, linenum, *err, newsrv->id);
2154 return -1;
2155 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002156 if (val <= 0) {
2157 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2158 file, linenum, val, args[cur_arg], newsrv->id);
2159 return -1;
2160 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002161 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002162 cur_arg += 2;
2163 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002164 else if (!strcmp(args[cur_arg], "track")) {
2165
2166 if (!*args[cur_arg + 1]) {
2167 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2168 file, linenum);
2169 return -1;
2170 }
2171
2172 newsrv->trackit = strdup(args[cur_arg + 1]);
2173
2174 cur_arg += 2;
2175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 else if (!strcmp(args[cur_arg], "check")) {
2177 global.maxsock++;
2178 do_check = 1;
2179 cur_arg += 1;
2180 }
2181 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2182 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002183#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002184 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2185 file, linenum, "source", "usesrc");
2186#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2188 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002189#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 return -1;
2191 }
2192 newsrv->state |= SRV_BIND_SRC;
2193 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2194 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002195 while (*(args[cur_arg])) {
2196 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002197#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2198#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002199 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2200 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2201 file, linenum, "usesrc", "source");
2202 return -1;
2203 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002204#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002205 if (!*args[cur_arg + 1]) {
2206 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2207 file, linenum, "usesrc");
2208 return -1;
2209 }
2210 if (!strcmp(args[cur_arg + 1], "client")) {
2211 newsrv->state |= SRV_TPROXY_CLI;
2212 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2213 newsrv->state |= SRV_TPROXY_CIP;
2214 } else {
2215 newsrv->state |= SRV_TPROXY_ADDR;
2216 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2217 }
2218 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002219#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002220 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002221#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002222 cur_arg += 2;
2223 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002224#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002225 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002226 file, linenum, "usesrc");
2227 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002228#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2229 } /* "usesrc" */
2230
2231 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2232#ifdef SO_BINDTODEVICE
2233 if (!*args[cur_arg + 1]) {
2234 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2235 file, linenum, args[0]);
2236 return -1;
2237 }
2238 if (newsrv->iface_name)
2239 free(newsrv->iface_name);
2240
2241 newsrv->iface_name = strdup(args[cur_arg + 1]);
2242 newsrv->iface_len = strlen(newsrv->iface_name);
2243 global.last_checks |= LSTCHK_NETADM;
2244#else
2245 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2246 file, linenum, args[0], args[cur_arg]);
2247 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002248#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002249 cur_arg += 2;
2250 continue;
2251 }
2252 /* this keyword in not an option of "source" */
2253 break;
2254 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002256 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2257 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2258 file, linenum, "usesrc", "source");
2259 return -1;
2260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002262 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 +02002263 file, linenum, newsrv->id);
2264 return -1;
2265 }
2266 }
2267
2268 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002269 if (newsrv->trackit) {
2270 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2271 file, linenum);
2272 return -1;
2273 }
2274
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002275 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2276 newsrv->check_port = newsrv->check_addr.sin_port;
2277
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2279 newsrv->check_port = realport; /* by default */
2280 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002281 /* not yet valid, because no port was set on
2282 * the server either. We'll check if we have
2283 * a known port on the first listener.
2284 */
2285 struct listener *l;
2286 l = curproxy->listen;
2287 if (l) {
2288 int port;
2289 port = (l->addr.ss_family == AF_INET6)
2290 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2291 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2292 newsrv->check_port = port;
2293 }
2294 }
2295 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2297 file, linenum, newsrv->id);
2298 return -1;
2299 }
2300 newsrv->state |= SRV_CHECKED;
2301 }
2302
2303 if (newsrv->state & SRV_BACKUP)
2304 curproxy->srv_bck++;
2305 else
2306 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002307
2308 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 }
2310 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002311 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 int facility;
2313
2314 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2315 curproxy->logfac1 = global.logfac1;
2316 curproxy->logsrv1 = global.logsrv1;
2317 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002318 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 curproxy->logfac2 = global.logfac2;
2320 curproxy->logsrv2 = global.logsrv2;
2321 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002322 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
2324 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002325 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326
2327 facility = get_log_facility(args[2]);
2328 if (facility < 0) {
2329 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2330 exit(1);
2331 }
2332
2333 level = 7; /* max syslog level = debug */
2334 if (*(args[3])) {
2335 level = get_log_level(args[3]);
2336 if (level < 0) {
2337 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2338 exit(1);
2339 }
2340 }
2341
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002342 minlvl = 0; /* limit syslog level to this level (emerg) */
2343 if (*(args[4])) {
2344 minlvl = get_log_level(args[4]);
2345 if (level < 0) {
2346 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2347 exit(1);
2348 }
2349 }
2350
Robert Tsai81ae1952007-12-05 10:47:29 +01002351 if (args[1][0] == '/') {
2352 logsrv.u.addr.sa_family = AF_UNIX;
2353 logsrv.u.un = *str2sun(args[1]);
2354 } else {
2355 logsrv.u.addr.sa_family = AF_INET;
2356 logsrv.u.in = *str2sa(args[1]);
2357 if (!logsrv.u.in.sin_port) {
2358 logsrv.u.in.sin_port =
2359 htons(SYSLOG_PORT);
2360 }
2361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362
2363 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002364 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 curproxy->logfac1 = facility;
2366 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002367 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002370 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 curproxy->logfac2 = facility;
2372 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002373 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 }
2375 else {
2376 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2377 return -1;
2378 }
2379 }
2380 else {
2381 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2382 file, linenum);
2383 return -1;
2384 }
2385 }
2386 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002387 int cur_arg;
2388
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2390 return 0;
2391
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002393 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2394 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 return -1;
2396 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002397
2398 /* we must first clear any optional default setting */
2399 curproxy->options &= ~PR_O_TPXY_MASK;
2400 free(curproxy->iface_name);
2401 curproxy->iface_name = NULL;
2402 curproxy->iface_len = 0;
2403
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 curproxy->source_addr = *str2sa(args[1]);
2405 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002406
2407 cur_arg = 2;
2408 while (*(args[cur_arg])) {
2409 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002410#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2411#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002412 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2413 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2414 file, linenum, "usesrc");
2415 return -1;
2416 }
2417#endif
2418 if (!*args[cur_arg + 1]) {
2419 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2420 file, linenum, "usesrc");
2421 return -1;
2422 }
2423
2424 if (!strcmp(args[cur_arg + 1], "client")) {
2425 curproxy->options |= PR_O_TPXY_CLI;
2426 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2427 curproxy->options |= PR_O_TPXY_CIP;
2428 } else {
2429 curproxy->options |= PR_O_TPXY_ADDR;
2430 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2431 }
2432 global.last_checks |= LSTCHK_NETADM;
2433#if !defined(CONFIG_HAP_LINUX_TPROXY)
2434 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002435#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002436#else /* no TPROXY support */
2437 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002438 file, linenum, "usesrc");
2439 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002440#endif
2441 cur_arg += 2;
2442 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002443 }
2444
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002445 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2446#ifdef SO_BINDTODEVICE
2447 if (!*args[cur_arg + 1]) {
2448 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2449 file, linenum, args[0]);
2450 return -1;
2451 }
2452 if (curproxy->iface_name)
2453 free(curproxy->iface_name);
2454
2455 curproxy->iface_name = strdup(args[cur_arg + 1]);
2456 curproxy->iface_len = strlen(curproxy->iface_name);
2457 global.last_checks |= LSTCHK_NETADM;
2458#else
2459 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2460 file, linenum, args[0], args[cur_arg]);
2461 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002462#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002463 cur_arg += 2;
2464 continue;
2465 }
2466 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2467 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002468 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002471 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2472 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2473 file, linenum, "usesrc", "source");
2474 return -1;
2475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2477 regex_t *preg;
2478 if (curproxy == &defproxy) {
2479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2480 return -1;
2481 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2483 return 0;
2484
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 if (*(args[1]) == 0 || *(args[2]) == 0) {
2486 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2487 file, linenum, args[0]);
2488 return -1;
2489 }
2490
2491 preg = calloc(1, sizeof(regex_t));
2492 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2493 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2494 return -1;
2495 }
2496
2497 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2498 if (err) {
2499 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2500 file, linenum, *err);
2501 return -1;
2502 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002503 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 }
2505 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2506 regex_t *preg;
2507 if (curproxy == &defproxy) {
2508 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2509 return -1;
2510 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002511 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2512 return 0;
2513
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 if (*(args[1]) == 0) {
2515 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2516 return -1;
2517 }
2518
2519 preg = calloc(1, sizeof(regex_t));
2520 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2521 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2522 return -1;
2523 }
2524
2525 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002526 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
2528 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2529 regex_t *preg;
2530 if (curproxy == &defproxy) {
2531 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2532 return -1;
2533 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2535 return 0;
2536
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 if (*(args[1]) == 0) {
2538 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2539 return -1;
2540 }
2541
2542 preg = calloc(1, sizeof(regex_t));
2543 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2544 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2545 return -1;
2546 }
2547
2548 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002549 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 }
2551 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2552 regex_t *preg;
2553 if (curproxy == &defproxy) {
2554 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2555 return -1;
2556 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2558 return 0;
2559
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 if (*(args[1]) == 0) {
2561 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2562 return -1;
2563 }
2564
2565 preg = calloc(1, sizeof(regex_t));
2566 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2567 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2568 return -1;
2569 }
2570
2571 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002572 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 }
2574 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2575 regex_t *preg;
2576 if (curproxy == &defproxy) {
2577 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2578 return -1;
2579 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2581 return 0;
2582
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 if (*(args[1]) == 0) {
2584 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2585 return -1;
2586 }
2587
2588 preg = calloc(1, sizeof(regex_t));
2589 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2590 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2591 return -1;
2592 }
2593
2594 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002595 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002597 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2598 regex_t *preg;
2599 if (curproxy == &defproxy) {
2600 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2601 return -1;
2602 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2604 return 0;
2605
Willy Tarreaub8750a82006-09-03 09:56:00 +02002606 if (*(args[1]) == 0) {
2607 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2608 return -1;
2609 }
2610
2611 preg = calloc(1, sizeof(regex_t));
2612 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2613 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2614 return -1;
2615 }
2616
2617 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002618 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002619 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002620 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2621 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002622 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2624 return -1;
2625 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002626 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2627 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002628
Willy Tarreau977b8e42006-12-29 14:19:17 +01002629 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002630 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2631 file, linenum, args[0]);
2632 return -1;
2633 }
2634
2635 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002637 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2638 }
2639
2640 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002641 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002642 }
2643 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2644 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2647 return -1;
2648 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002649 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2650 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002651
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002653 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2654 file, linenum, args[0]);
2655 return -1;
2656 }
2657
2658 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002659 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002660 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2661 }
2662
2663 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002664 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2667 regex_t *preg;
2668 if (curproxy == &defproxy) {
2669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2670 return -1;
2671 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002672 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2673 return 0;
2674
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 if (*(args[1]) == 0 || *(args[2]) == 0) {
2676 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2677 file, linenum, args[0]);
2678 return -1;
2679 }
2680
2681 preg = calloc(1, sizeof(regex_t));
2682 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2683 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2684 return -1;
2685 }
2686
2687 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2688 if (err) {
2689 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2690 file, linenum, *err);
2691 return -1;
2692 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002693 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
2695 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2696 regex_t *preg;
2697 if (curproxy == &defproxy) {
2698 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2699 return -1;
2700 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002701 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2702 return 0;
2703
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 if (*(args[1]) == 0) {
2705 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2706 return -1;
2707 }
2708
2709 preg = calloc(1, sizeof(regex_t));
2710 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2711 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2712 return -1;
2713 }
2714
2715 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002716 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
2718 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2719 regex_t *preg;
2720 if (curproxy == &defproxy) {
2721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2722 return -1;
2723 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002724 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2725 return 0;
2726
Willy Tarreaubaaee002006-06-26 02:48:02 +02002727 if (*(args[1]) == 0) {
2728 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2729 return -1;
2730 }
2731
2732 preg = calloc(1, sizeof(regex_t));
2733 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2734 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2735 return -1;
2736 }
2737
2738 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002739 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2742 regex_t *preg;
2743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2745 return -1;
2746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2748 return 0;
2749
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 if (*(args[1]) == 0) {
2751 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2752 return -1;
2753 }
2754
2755 preg = calloc(1, sizeof(regex_t));
2756 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2757 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2758 return -1;
2759 }
2760
2761 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002762 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2765 regex_t *preg;
2766 if (curproxy == &defproxy) {
2767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2768 return -1;
2769 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002770 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2771 return 0;
2772
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 if (*(args[1]) == 0) {
2774 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2775 return -1;
2776 }
2777
2778 preg = calloc(1, sizeof(regex_t));
2779 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2780 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2781 return -1;
2782 }
2783
2784 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002785 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002787 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2788 regex_t *preg;
2789 if (curproxy == &defproxy) {
2790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2791 return -1;
2792 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002793 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2794 return 0;
2795
Willy Tarreaub8750a82006-09-03 09:56:00 +02002796 if (*(args[1]) == 0) {
2797 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2798 return -1;
2799 }
2800
2801 preg = calloc(1, sizeof(regex_t));
2802 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2803 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2804 return -1;
2805 }
2806
2807 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002808 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2811 if (curproxy == &defproxy) {
2812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2813 return -1;
2814 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002815 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2816 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817
2818 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2819 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2820 return 0;
2821 }
2822
2823 if (*(args[1]) == 0) {
2824 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2825 return -1;
2826 }
2827
2828 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002829 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002830 }
2831 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2832 regex_t *preg;
2833
2834 if (*(args[1]) == 0 || *(args[2]) == 0) {
2835 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2836 file, linenum, args[0]);
2837 return -1;
2838 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2840 return 0;
2841
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 preg = calloc(1, sizeof(regex_t));
2843 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2844 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2845 return -1;
2846 }
2847
2848 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2849 if (err) {
2850 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2851 file, linenum, *err);
2852 return -1;
2853 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002854 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002855 }
2856 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2857 regex_t *preg;
2858 if (curproxy == &defproxy) {
2859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2860 return -1;
2861 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002862 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2863 return 0;
2864
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 if (*(args[1]) == 0) {
2866 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2867 return -1;
2868 }
2869
2870 preg = calloc(1, sizeof(regex_t));
2871 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2872 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2873 return -1;
2874 }
2875
2876 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2877 if (err) {
2878 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2879 file, linenum, *err);
2880 return -1;
2881 }
2882 }
2883 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2884 regex_t *preg;
2885 if (curproxy == &defproxy) {
2886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2887 return -1;
2888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2890 return 0;
2891
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 if (*(args[1]) == 0) {
2893 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2894 return -1;
2895 }
2896
2897 preg = calloc(1, sizeof(regex_t));
2898 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2899 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2900 return -1;
2901 }
2902
2903 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2904 if (err) {
2905 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2906 file, linenum, *err);
2907 return -1;
2908 }
2909 }
2910 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2911 regex_t *preg;
2912 if (curproxy == &defproxy) {
2913 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2914 return -1;
2915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002916 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2917 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918
2919 if (*(args[1]) == 0 || *(args[2]) == 0) {
2920 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2921 file, linenum, args[0]);
2922 return -1;
2923 }
2924
2925 preg = calloc(1, sizeof(regex_t));
2926 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2927 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2928 return -1;
2929 }
2930
2931 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2932 if (err) {
2933 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2934 file, linenum, *err);
2935 return -1;
2936 }
2937 }
2938 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2939 regex_t *preg;
2940 if (curproxy == &defproxy) {
2941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2942 return -1;
2943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002944 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2945 return 0;
2946
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 if (*(args[1]) == 0) {
2948 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2949 return -1;
2950 }
2951
2952 preg = calloc(1, sizeof(regex_t));
2953 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2954 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2955 return -1;
2956 }
2957
2958 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2959 if (err) {
2960 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2961 file, linenum, *err);
2962 return -1;
2963 }
2964 }
2965 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2966 regex_t *preg;
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;
2973
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 if (*(args[1]) == 0) {
2975 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2976 return -1;
2977 }
2978
2979 preg = calloc(1, sizeof(regex_t));
2980 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2981 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2982 return -1;
2983 }
2984
2985 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2986 if (err) {
2987 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2988 file, linenum, *err);
2989 return -1;
2990 }
2991 }
2992 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2993 if (curproxy == &defproxy) {
2994 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2995 return -1;
2996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002997 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2998 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999
3000 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3001 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
3002 return 0;
3003 }
3004
3005 if (*(args[1]) == 0) {
3006 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
3007 return -1;
3008 }
3009
3010 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3011 }
3012 else if (!strcmp(args[0], "errorloc") ||
3013 !strcmp(args[0], "errorloc302") ||
3014 !strcmp(args[0], "errorloc303")) { /* error location */
3015 int errnum, errlen;
3016 char *err;
3017
Willy Tarreau977b8e42006-12-29 14:19:17 +01003018 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3019 return 0;
3020
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003022 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 return -1;
3024 }
3025
3026 errnum = atol(args[1]);
3027 if (!strcmp(args[0], "errorloc303")) {
3028 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3029 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3030 } else {
3031 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3032 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3033 }
3034
Willy Tarreau0f772532006-12-23 20:51:41 +01003035 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3036 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003037 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003038 curproxy->errmsg[rc].str = err;
3039 curproxy->errmsg[rc].len = errlen;
3040 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003043
3044 if (rc >= HTTP_ERR_SIZE) {
3045 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3046 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 free(err);
3048 }
3049 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003050 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3051 int errnum, errlen, fd;
3052 char *err;
3053 struct stat stat;
3054
3055 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3056 return 0;
3057
3058 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003059 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003060 return -1;
3061 }
3062
3063 fd = open(args[2], O_RDONLY);
3064 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3065 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3066 file, linenum, args[2], args[1]);
3067 if (fd >= 0)
3068 close(fd);
3069 return -1;
3070 }
3071
3072 if (stat.st_size <= BUFSIZE) {
3073 errlen = stat.st_size;
3074 } else {
3075 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3076 file, linenum, args[2], BUFSIZE);
3077 errlen = BUFSIZE;
3078 }
3079
3080 err = malloc(errlen); /* malloc() must succeed during parsing */
3081 errnum = read(fd, err, errlen);
3082 if (errnum != errlen) {
3083 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3084 file, linenum, args[2], args[1]);
3085 close(fd);
3086 free(err);
3087 return -1;
3088 }
3089 close(fd);
3090
3091 errnum = atol(args[1]);
3092 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3093 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003094 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003095 curproxy->errmsg[rc].str = err;
3096 curproxy->errmsg[rc].len = errlen;
3097 break;
3098 }
3099 }
3100
3101 if (rc >= HTTP_ERR_SIZE) {
3102 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3103 file, linenum, errnum);
3104 free(err);
3105 }
3106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003108 struct cfg_kw_list *kwl;
3109 int index;
3110
3111 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3112 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3113 if (kwl->kw[index].section != CFG_LISTEN)
3114 continue;
3115 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3116 /* prepare error message just in case */
3117 snprintf(trash, sizeof(trash),
3118 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003119 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3120 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003121 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3122 return -1;
3123 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003124 else if (rc > 0) {
3125 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3126 return 0;
3127 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003128 return 0;
3129 }
3130 }
3131 }
3132
Willy Tarreau6daf3432008-01-22 16:44:08 +01003133 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 return -1;
3135 }
3136 return 0;
3137}
3138
3139
3140/*
3141 * This function reads and parses the configuration file given in the argument.
3142 * returns 0 if OK, -1 if error.
3143 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003144int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003146 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 FILE *f;
3148 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 int confsect = CFG_NONE;
3151
3152 struct proxy *curproxy = NULL;
3153 struct server *newsrv = NULL;
3154
3155 if ((f=fopen(file,"r")) == NULL)
3156 return -1;
3157
3158 init_default_instance();
3159
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003160 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003161 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003162 char *end;
3163 char *args[MAX_LINE_ARGS + 1];
3164 char *line = thisline;
3165
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 linenum++;
3167
3168 end = line + strlen(line);
3169
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003170 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3171 /* Check if we reached the limit and the last char is not \n.
3172 * Watch out for the last line without the terminating '\n'!
3173 */
3174 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003175 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003176 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003177 }
3178
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003180 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 line++;
3182
3183 arg = 0;
3184 args[arg] = line;
3185
3186 while (*line && arg < MAX_LINE_ARGS) {
3187 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3188 * C equivalent value. Other combinations left unchanged (eg: \1).
3189 */
3190 if (*line == '\\') {
3191 int skip = 0;
3192 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3193 *line = line[1];
3194 skip = 1;
3195 }
3196 else if (line[1] == 'r') {
3197 *line = '\r';
3198 skip = 1;
3199 }
3200 else if (line[1] == 'n') {
3201 *line = '\n';
3202 skip = 1;
3203 }
3204 else if (line[1] == 't') {
3205 *line = '\t';
3206 skip = 1;
3207 }
3208 else if (line[1] == 'x') {
3209 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3210 unsigned char hex1, hex2;
3211 hex1 = toupper(line[2]) - '0';
3212 hex2 = toupper(line[3]) - '0';
3213 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3214 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3215 *line = (hex1<<4) + hex2;
3216 skip = 3;
3217 }
3218 else {
3219 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003220 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
3222 }
3223 if (skip) {
3224 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3225 end -= skip;
3226 }
3227 line++;
3228 }
3229 else if (*line == '#' || *line == '\n' || *line == '\r') {
3230 /* end of string, end of loop */
3231 *line = 0;
3232 break;
3233 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003234 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003236 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003237 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 line++;
3239 args[++arg] = line;
3240 }
3241 else {
3242 line++;
3243 }
3244 }
3245
3246 /* empty line */
3247 if (!**args)
3248 continue;
3249
Willy Tarreau540abe42007-05-02 20:50:16 +02003250 /* zero out remaining args and ensure that at least one entry
3251 * is zeroed out.
3252 */
3253 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 args[arg] = line;
3255 }
3256
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003257 if (!strcmp(args[0], "no")) {
3258 inv = 1;
3259 for (arg=0; *args[arg+1]; arg++)
3260 args[arg] = args[arg+1]; // shift args after inversion
3261 }
3262
3263 if (inv && strcmp(args[0], "option")) {
3264 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003265 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003266 }
3267
Willy Tarreau977b8e42006-12-29 14:19:17 +01003268 if (!strcmp(args[0], "listen") ||
3269 !strcmp(args[0], "frontend") ||
3270 !strcmp(args[0], "backend") ||
3271 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003272 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003274 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003275 cursection = strdup(args[0]);
3276 }
3277 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003279 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003280 cursection = strdup(args[0]);
3281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 /* else it's a section keyword */
3283
3284 switch (confsect) {
3285 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003286 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003287 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 break;
3289 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003290 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003291 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 break;
3293 default:
3294 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003295 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003298 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003299 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 fclose(f);
3301
3302 /*
3303 * Now, check for the integrity of all that we have collected.
3304 */
3305
3306 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003307 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003309 /* first, we will invert the proxy list order */
3310 curproxy = NULL;
3311 while (proxy) {
3312 struct proxy *next;
3313
3314 next = proxy->next;
3315 proxy->next = curproxy;
3316 curproxy = proxy;
3317 if (!next)
3318 break;
3319 proxy = next;
3320 }
3321
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 if ((curproxy = proxy) == NULL) {
3323 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3324 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003325 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003326 }
3327
3328 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003329 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003330 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003331
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003333 /* ensure we don't keep listeners uselessly bound */
3334 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 curproxy = curproxy->next;
3336 continue;
3337 }
3338
Willy Tarreauff01a212009-03-15 13:46:16 +01003339 switch (curproxy->mode) {
3340 case PR_MODE_HEALTH:
3341 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3342 if (!(curproxy->cap & PR_CAP_FE)) {
3343 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3344 file, proxy_type_str(curproxy), curproxy->id);
3345 cfgerr++;
3346 }
3347
3348 if (curproxy->srv != NULL)
3349 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3350 file, proxy_type_str(curproxy), curproxy->id);
3351 break;
3352
3353 case PR_MODE_TCP:
3354 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3355 break;
3356
3357 case PR_MODE_HTTP:
3358 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3359 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3360 file, curproxy->id);
3361 cfgerr++;
3362 }
3363 break;
3364 }
3365
3366 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003367 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 +01003368 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 cfgerr++;
3370 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003371
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003372 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3373 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3374 if (curproxy->options & PR_O_TRANSP) {
3375 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3376 file, proxy_type_str(curproxy), curproxy->id);
3377 cfgerr++;
3378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003380 else if (curproxy->srv == NULL) {
3381 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3382 file, proxy_type_str(curproxy), curproxy->id);
3383 cfgerr++;
3384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003386 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3387 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3388 file, proxy_type_str(curproxy), curproxy->id);
3389 }
3390 }
3391 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3392 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3393 /* If no LB algo is set in a backend, and we're not in
3394 * transparent mode, dispatch mode nor proxy mode, we
3395 * want to use balance roundrobin by default.
3396 */
3397 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3398 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003401
Willy Tarreau82936582007-11-30 15:20:09 +01003402 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3403 curproxy->options &= ~PR_O_DISABLE404;
3404 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3405 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3406 }
3407
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003408 /* if a default backend was specified, let's find it */
3409 if (curproxy->defbe.name) {
3410 struct proxy *target;
3411
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003412 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3413 if (!target) {
3414 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3415 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003416 cfgerr++;
3417 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003418 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3419 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003420 } else {
3421 free(curproxy->defbe.name);
3422 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003423 /* we force the backend to be present on at least all of
3424 * the frontend's processes.
3425 */
3426 target->bind_proc = curproxy->bind_proc ?
3427 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
3429 }
3430
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003431 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003432 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3433 /* map jump target for ACT_SETBE in req_rep chain */
3434 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003435 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003436 struct proxy *target;
3437
Willy Tarreaua496b602006-12-17 23:15:24 +01003438 if (exp->action != ACT_SETBE)
3439 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003440
3441 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3442 if (!target) {
3443 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3444 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003445 cfgerr++;
3446 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003447 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3448 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003449 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003450 } else {
3451 free((void *)exp->replace);
3452 exp->replace = (const char *)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 Tarreaua496b602006-12-17 23:15:24 +01003458 }
3459 }
3460 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003461
3462 /* find the target proxy for 'use_backend' rules */
3463 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003464 struct proxy *target;
3465
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003466 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003467
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003468 if (!target) {
3469 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3470 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003471 cfgerr++;
3472 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003473 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3474 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003475 cfgerr++;
3476 } else {
3477 free((void *)rule->be.name);
3478 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003479 /* we force the backend to be present on at least all of
3480 * the frontend's processes.
3481 */
3482 target->bind_proc = curproxy->bind_proc ?
3483 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003484 }
3485 }
3486
Willy Tarreau2738a142006-07-08 17:28:09 +02003487 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003488 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003489 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003490 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003491 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003492 " | While not properly invalid, you will certainly encounter various problems\n"
3493 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003494 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003495 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003496 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003497
Willy Tarreau1fa31262007-12-03 00:36:16 +01003498 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3499 * We must still support older configurations, so let's find out whether those
3500 * parameters have been set or must be copied from contimeouts.
3501 */
3502 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003503 if (!curproxy->timeout.tarpit ||
3504 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003505 /* tarpit timeout not set. We search in the following order:
3506 * default.tarpit, curr.connect, default.connect.
3507 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003508 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003509 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003510 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003511 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003512 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003513 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003514 }
3515 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003516 (!curproxy->timeout.queue ||
3517 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003518 /* queue timeout not set. We search in the following order:
3519 * default.queue, curr.connect, default.connect.
3520 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003521 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003522 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003523 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003524 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003525 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003526 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003527 }
3528 }
3529
Willy Tarreauf3c69202006-07-09 16:42:34 +02003530 if (curproxy->options & PR_O_SSL3_CHK) {
3531 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3532 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3533 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3534 }
3535
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003536 /* The small pools required for the capture lists */
3537 if (curproxy->nb_req_cap)
3538 curproxy->req_cap_pool = create_pool("ptrcap",
3539 curproxy->nb_req_cap * sizeof(char *),
3540 MEM_F_SHARED);
3541 if (curproxy->nb_rsp_cap)
3542 curproxy->rsp_cap_pool = create_pool("ptrcap",
3543 curproxy->nb_rsp_cap * sizeof(char *),
3544 MEM_F_SHARED);
3545
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003546 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3547 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3548 MEM_F_SHARED);
3549
Willy Tarreau86034312006-12-29 00:10:33 +01003550 /* for backwards compatibility with "listen" instances, if
3551 * fullconn is not set but maxconn is set, then maxconn
3552 * is used.
3553 */
3554 if (!curproxy->fullconn)
3555 curproxy->fullconn = curproxy->maxconn;
3556
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 /* first, we will invert the servers list order */
3558 newsrv = NULL;
3559 while (curproxy->srv) {
3560 struct server *next;
3561
3562 next = curproxy->srv->next;
3563 curproxy->srv->next = newsrv;
3564 newsrv = curproxy->srv;
3565 if (!next)
3566 break;
3567 curproxy->srv = next;
3568 }
3569
Willy Tarreau20697042007-11-15 23:26:18 +01003570 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003571 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572
Willy Tarreaub625a082007-11-26 01:15:43 +01003573 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003574 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003575 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003576 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3577 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003578 else
3579 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580
3581 if (curproxy->options & PR_O_LOGASAP)
3582 curproxy->to_log &= ~LW_BYTES;
3583
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003585 * ensure that we're not cross-dressing a TCP server into HTTP.
3586 */
3587 newsrv = curproxy->srv;
3588 while (newsrv != NULL) {
3589 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003590 Alert("parsing [%s:%d] : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3591 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003592 goto err;
3593 }
3594 newsrv = newsrv->next;
3595 }
3596
3597 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 * If this server supports a maxconn parameter, it needs a dedicated
3599 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003600 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 */
3602 newsrv = curproxy->srv;
3603 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003604 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 /* Only 'minconn' was specified, or it was higher than or equal
3606 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3607 * this will avoid further useless expensive computations.
3608 */
3609 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003610 } else if (newsrv->maxconn && !newsrv->minconn) {
3611 /* minconn was not specified, so we set it to maxconn */
3612 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003614 Alert("parsing [%s:%d] : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3615 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003616 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003619 if (newsrv->trackit) {
3620 struct proxy *px;
3621 struct server *srv;
3622 char *pname, *sname;
3623
3624 pname = newsrv->trackit;
3625 sname = strrchr(pname, '/');
3626
3627 if (sname)
3628 *sname++ = '\0';
3629 else {
3630 sname = pname;
3631 pname = NULL;
3632 }
3633
3634 if (pname) {
3635 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3636 if (!px) {
3637 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3638 file, proxy_type_str(curproxy), curproxy->id,
3639 newsrv->id, pname);
3640 return -1;
3641 }
3642 } else
3643 px = curproxy;
3644
3645 srv = findserver(px, sname);
3646 if (!srv) {
3647 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3648 file, proxy_type_str(curproxy), curproxy->id,
3649 newsrv->id, sname);
3650 return -1;
3651 }
3652
3653 if (!(srv->state & SRV_CHECKED)) {
3654 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3655 "tracing as it does not have checks enabled.\n",
3656 file, proxy_type_str(curproxy), curproxy->id,
3657 newsrv->id, px->id, srv->id);
3658 return -1;
3659 }
3660
3661 if (curproxy != px &&
3662 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3663 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3664 "tracing: disable-on-404 option inconsistency.\n",
3665 file, proxy_type_str(curproxy), curproxy->id,
3666 newsrv->id, px->id, srv->id);
3667 return -1;
3668 }
3669
3670 newsrv->tracked = srv;
3671 newsrv->tracknext = srv->tracknext;
3672 srv->tracknext = newsrv;
3673
3674 free(newsrv->trackit);
3675 }
3676
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 newsrv = newsrv->next;
3678 }
3679
Willy Tarreaue6b98942007-10-29 01:09:36 +01003680 /* adjust this proxy's listeners */
3681 listener = curproxy->listen;
3682 while (listener) {
3683 if (curproxy->options & PR_O_TCP_NOLING)
3684 listener->options |= LI_O_NOLINGER;
3685 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003686 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003687 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003688 listener->accept = event_accept;
3689 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003690 listener->handler = process_session;
3691
3692 if (curproxy->mode == PR_MODE_HTTP)
3693 listener->analysers |= AN_REQ_HTTP_HDR;
3694
Willy Tarreaud869b242009-03-15 14:43:58 +01003695 if (curproxy->tcp_req.inspect_delay ||
3696 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003697 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003698
3699 listener = listener->next;
3700 }
3701
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 curproxy = curproxy->next;
3703 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003704
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 if (cfgerr > 0) {
3706 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003707 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003709
3710 /*
3711 * Recount currently required checks.
3712 */
3713
3714 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3715 int optnum;
3716
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003717 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3718 if (curproxy->options & cfg_opts[optnum].val)
3719 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003720
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003721 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3722 if (curproxy->options2 & cfg_opts2[optnum].val)
3723 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003724 }
3725
Willy Tarreaua534fea2008-08-03 12:19:50 +02003726 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003727 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003728 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003729
3730 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003731 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003732 cursection = NULL;
3733 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734}
3735
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003736/*
3737 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3738 * parsing sessions.
3739 */
3740void cfg_register_keywords(struct cfg_kw_list *kwl)
3741{
3742 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3743}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003745/*
3746 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3747 */
3748void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3749{
3750 LIST_DEL(&kwl->list);
3751 LIST_INIT(&kwl->list);
3752}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753
3754/*
3755 * Local variables:
3756 * c-indent-level: 8
3757 * c-basic-offset: 8
3758 * End:
3759 */