blob: cddca1e845b2130b867981d3e05cb0f0778cb0a3 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020046#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010047#include <proto/protocols.h>
48#include <proto/proto_tcp.h>
49#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010050#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010052#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/task.h>
54
55
Willy Tarreauf3c69202006-07-09 16:42:34 +020056/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
57 * ssl-hello-chk option to ensure that the remote server speaks SSL.
58 *
59 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
60 */
61const char sslv3_client_hello_pkt[] = {
62 "\x16" /* ContentType : 0x16 = Hanshake */
63 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
64 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
65 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
66 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
67 "\x03\x00" /* Hello Version : 0x0300 = v3 */
68 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
69 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
70 "\x00" /* Session ID length : empty (no session ID) */
71 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
72 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
73 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
74 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
75 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
76 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
77 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
78 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
79 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
80 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
81 "\x00\x38" "\x00\x39" "\x00\x3A"
82 "\x01" /* Compression Length : 0x01 = 1 byte for types */
83 "\x00" /* Compression Type : 0x00 = NULL compression */
84};
85
Willy Tarreau3842f002009-06-14 11:39:52 +020086/* various keyword modifiers */
87enum kw_mod {
88 KWM_STD = 0, /* normal */
89 KWM_NO, /* "no" prefixed before the keyword */
90 KWM_DEF, /* "default" prefixed before the keyword */
91};
92
Willy Tarreau13943ab2006-12-31 00:24:10 +010093/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010094struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010095 const char *name;
96 unsigned int val;
97 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010098 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010099};
100
101/* proxy->options */
102static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100104 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100105 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100106 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100107 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100108 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
109 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
110 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
111 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
112 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
113 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
114 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
115 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100117 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
118 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100119#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100120 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100121#endif
122
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100123 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100124};
125
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126/* proxy->options2 */
127static const struct cfg_opt cfg_opts2[] =
128{
129#ifdef CONFIG_HAP_LINUX_SPLICE
130 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
131 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
132 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
133#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200134 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
135 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200136 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
137 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200138 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200139 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140 { NULL, 0, 0, 0 }
141};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau6daf3432008-01-22 16:44:08 +0100143static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
145int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100146int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200147
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200148/* List head of all known configuration keywords */
149static struct cfg_kw_list cfg_keywords = {
150 .list = LIST_HEAD_INIT(cfg_keywords.list)
151};
152
Willy Tarreaubaaee002006-06-26 02:48:02 +0200153/*
154 * converts <str> to a list of listeners which are dynamically allocated.
155 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
156 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
157 * - <port> is a numerical port from 1 to 65535 ;
158 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
159 * This can be repeated as many times as necessary, separated by a coma.
160 * The <tail> argument is a pointer to a current list which should be appended
161 * to the tail of the new list. The pointer to the new list is returned.
162 */
163static struct listener *str2listener(char *str, struct listener *tail)
164{
165 struct listener *l;
166 char *c, *next, *range, *dupstr;
167 int port, end;
168
169 next = dupstr = strdup(str);
170
171 while (next && *next) {
172 struct sockaddr_storage ss;
173
174 str = next;
175 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100176 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 *next++ = 0;
178 }
179
180 /* 2) look for the addr/port delimiter, it's the last colon. */
181 if ((range = strrchr(str, ':')) == NULL) {
182 Alert("Missing port number: '%s'\n", str);
183 goto fail;
184 }
185
186 *range++ = 0;
187
188 if (strrchr(str, ':') != NULL) {
189 /* IPv6 address contains ':' */
190 memset(&ss, 0, sizeof(ss));
191 ss.ss_family = AF_INET6;
192
193 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
194 Alert("Invalid server address: '%s'\n", str);
195 goto fail;
196 }
197 }
198 else {
199 memset(&ss, 0, sizeof(ss));
200 ss.ss_family = AF_INET;
201
202 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
203 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
204 }
205 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
206 struct hostent *he;
207
208 if ((he = gethostbyname(str)) == NULL) {
209 Alert("Invalid server name: '%s'\n", str);
210 goto fail;
211 }
212 else
213 ((struct sockaddr_in *)&ss)->sin_addr =
214 *(struct in_addr *) *(he->h_addr_list);
215 }
216 }
217
218 /* 3) look for the port-end delimiter */
219 if ((c = strchr(range, '-')) != NULL) {
220 *c++ = 0;
221 end = atol(c);
222 }
223 else {
224 end = atol(range);
225 }
226
227 port = atol(range);
228
229 if (port < 1 || port > 65535) {
230 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
231 goto fail;
232 }
233
234 if (end < 1 || end > 65535) {
235 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
236 goto fail;
237 }
238
239 for (; port <= end; port++) {
240 l = (struct listener *)calloc(1, sizeof(struct listener));
241 l->next = tail;
242 tail = l;
243
244 l->fd = -1;
245 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100246 l->state = LI_INIT;
247
248 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100250 tcpv6_add_listener(l);
251 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100253 tcpv4_add_listener(l);
254 }
255 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 } /* end for(port) */
257 } /* end while(next) */
258 free(dupstr);
259 return tail;
260 fail:
261 free(dupstr);
262 return NULL;
263}
264
Willy Tarreau977b8e42006-12-29 14:19:17 +0100265/*
266 * Sends a warning if proxy <proxy> does not have at least one of the
267 * capabilities in <cap>. An optionnal <hint> may be added at the end
268 * of the warning to help the user. Returns 1 if a warning was emitted
269 * or 0 if the condition is valid.
270 */
271int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
272{
273 char *msg;
274
275 switch (cap) {
276 case PR_CAP_BE: msg = "no backend"; break;
277 case PR_CAP_FE: msg = "no frontend"; break;
278 case PR_CAP_RS: msg = "no ruleset"; break;
279 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
280 default: msg = "not enough"; break;
281 }
282
283 if (!(proxy->cap & cap)) {
284 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100285 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100286 return 1;
287 }
288 return 0;
289}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290
Willy Tarreau61d18892009-03-31 10:49:21 +0200291/* Report a warning if a rule is placed after a 'block' rule.
292 * Return 1 if the warning has been emitted, otherwise 0.
293 */
294int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
295{
296 if (!LIST_ISEMPTY(&proxy->block_cond)) {
297 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
298 file, line, arg);
299 return 1;
300 }
301 return 0;
302}
303
304/* Report a warning if a rule is placed after a reqrewrite rule.
305 * Return 1 if the warning has been emitted, otherwise 0.
306 */
307int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
308{
309 if (proxy->req_exp) {
310 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
311 file, line, arg);
312 return 1;
313 }
314 return 0;
315}
316
317/* Report a warning if a rule is placed after a reqadd rule.
318 * Return 1 if the warning has been emitted, otherwise 0.
319 */
320int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
321{
322 if (proxy->nb_reqadd) {
323 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
324 file, line, arg);
325 return 1;
326 }
327 return 0;
328}
329
330/* Report a warning if a rule is placed after a redirect rule.
331 * Return 1 if the warning has been emitted, otherwise 0.
332 */
333int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
334{
335 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
336 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
337 file, line, arg);
338 return 1;
339 }
340 return 0;
341}
342
343/* Report a warning if a rule is placed after a 'use_backend' rule.
344 * Return 1 if the warning has been emitted, otherwise 0.
345 */
346int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
347{
348 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
349 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
350 file, line, arg);
351 return 1;
352 }
353 return 0;
354}
355
356/* report a warning if a block rule is dangerously placed */
357int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
358{
359 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
360 warnif_rule_after_reqadd(proxy, file, line, arg) ||
361 warnif_rule_after_redirect(proxy, file, line, arg) ||
362 warnif_rule_after_use_backend(proxy, file, line, arg);
363}
364
365/* report a warning if a reqxxx rule is dangerously placed */
366int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
367{
368 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
369 warnif_rule_after_redirect(proxy, file, line, arg) ||
370 warnif_rule_after_use_backend(proxy, file, line, arg);
371}
372
373/* report a warning if a reqadd rule is dangerously placed */
374int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
375{
376 return warnif_rule_after_redirect(proxy, file, line, arg) ||
377 warnif_rule_after_use_backend(proxy, file, line, arg);
378}
379
Willy Tarreaubaaee002006-06-26 02:48:02 +0200380/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200381 * parse a line in a <global> section. Returns the error code, 0 if OK, or
382 * any combination of :
383 * - ERR_ABORT: must abort ASAP
384 * - ERR_FATAL: we can continue parsing but not start the service
385 * - ERR_WARN: a warning has been emitted
386 * - ERR_ALERT: an alert has been emitted
387 * Only the two first ones can stop processing, the two others are just
388 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200389 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200390int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200391{
Willy Tarreau058e9072009-07-20 09:30:05 +0200392 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200393
394 if (!strcmp(args[0], "global")) { /* new section */
395 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397 }
398 else if (!strcmp(args[0], "daemon")) {
399 global.mode |= MODE_DAEMON;
400 }
401 else if (!strcmp(args[0], "debug")) {
402 global.mode |= MODE_DEBUG;
403 }
404 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100405 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200406 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200407 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100408 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200409 }
410 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100411 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200413 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100414 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200415 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100416 else if (!strcmp(args[0], "nosplice")) {
417 global.tune.options &= ~GTUNE_USE_SPLICE;
418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200419 else if (!strcmp(args[0], "quiet")) {
420 global.mode |= MODE_QUIET;
421 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200422 else if (!strcmp(args[0], "tune.maxpollevents")) {
423 if (global.tune.maxpollevents != 0) {
424 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200425 err_code |= ERR_ALERT;
426 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200427 }
428 if (*(args[1]) == 0) {
429 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200430 err_code |= ERR_ALERT | ERR_FATAL;
431 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200432 }
433 global.tune.maxpollevents = atol(args[1]);
434 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100435 else if (!strcmp(args[0], "tune.maxaccept")) {
436 if (global.tune.maxaccept != 0) {
437 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200438 err_code |= ERR_ALERT;
439 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100440 }
441 if (*(args[1]) == 0) {
442 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 err_code |= ERR_ALERT | ERR_FATAL;
444 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100445 }
446 global.tune.maxaccept = atol(args[1]);
447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448 else if (!strcmp(args[0], "uid")) {
449 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200450 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200451 err_code |= ERR_ALERT;
452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 }
454 if (*(args[1]) == 0) {
455 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200456 err_code |= ERR_ALERT | ERR_FATAL;
457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 }
459 global.uid = atol(args[1]);
460 }
461 else if (!strcmp(args[0], "gid")) {
462 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200463 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 err_code |= ERR_ALERT;
465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 }
467 if (*(args[1]) == 0) {
468 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 err_code |= ERR_ALERT | ERR_FATAL;
470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
472 global.gid = atol(args[1]);
473 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200474 /* user/group name handling */
475 else if (!strcmp(args[0], "user")) {
476 struct passwd *ha_user;
477 if (global.uid != 0) {
478 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200479 err_code |= ERR_ALERT;
480 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200481 }
482 errno = 0;
483 ha_user = getpwnam(args[1]);
484 if (ha_user != NULL) {
485 global.uid = (int)ha_user->pw_uid;
486 }
487 else {
488 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200490 }
491 }
492 else if (!strcmp(args[0], "group")) {
493 struct group *ha_group;
494 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200495 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200496 err_code |= ERR_ALERT;
497 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200498 }
499 errno = 0;
500 ha_group = getgrnam(args[1]);
501 if (ha_group != NULL) {
502 global.gid = (int)ha_group->gr_gid;
503 }
504 else {
505 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200507 }
508 }
509 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "nbproc")) {
511 if (global.nbproc != 0) {
512 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT;
514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200515 }
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200518 err_code |= ERR_ALERT | ERR_FATAL;
519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
521 global.nbproc = atol(args[1]);
522 }
523 else if (!strcmp(args[0], "maxconn")) {
524 if (global.maxconn != 0) {
525 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200526 err_code |= ERR_ALERT;
527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 }
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533 }
534 global.maxconn = atol(args[1]);
535#ifdef SYSTEM_MAXCONN
536 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
537 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);
538 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 }
541#endif /* SYSTEM_MAXCONN */
542 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100543 else if (!strcmp(args[0], "maxpipes")) {
544 if (global.maxpipes != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100553 }
554 global.maxpipes = atol(args[1]);
555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 else if (!strcmp(args[0], "ulimit-n")) {
557 if (global.rlimit_nofile != 0) {
558 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200559 err_code |= ERR_ALERT;
560 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200561 }
562 if (*(args[1]) == 0) {
563 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 }
567 global.rlimit_nofile = atol(args[1]);
568 }
569 else if (!strcmp(args[0], "chroot")) {
570 if (global.chroot != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200572 err_code |= ERR_ALERT;
573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 }
580 global.chroot = strdup(args[1]);
581 }
582 else if (!strcmp(args[0], "pidfile")) {
583 if (global.pidfile != NULL) {
584 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200585 err_code |= ERR_ALERT;
586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 }
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 }
593 global.pidfile = strdup(args[1]);
594 }
595 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100596 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200597 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598
599 if (*(args[1]) == 0 || *(args[2]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 }
604
605 facility = get_log_facility(args[2]);
606 if (facility < 0) {
607 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT | ERR_FATAL;
609 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 }
611
612 level = 7; /* max syslog level = debug */
613 if (*(args[3])) {
614 level = get_log_level(args[3]);
615 if (level < 0) {
616 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT | ERR_FATAL;
618 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619 }
620 }
621
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200622 minlvl = 0; /* limit syslog level to this level (emerg) */
623 if (*(args[4])) {
624 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200625 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200626 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT | ERR_FATAL;
628 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200629 }
630 }
631
Robert Tsai81ae1952007-12-05 10:47:29 +0100632 if (args[1][0] == '/') {
633 logsrv.u.addr.sa_family = AF_UNIX;
634 logsrv.u.un = *str2sun(args[1]);
635 } else {
636 logsrv.u.addr.sa_family = AF_INET;
637 logsrv.u.in = *str2sa(args[1]);
638 if (!logsrv.u.in.sin_port)
639 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641
642 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100643 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 global.logfac1 = facility;
645 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200646 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100649 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200650 global.logfac2 = facility;
651 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200652 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 }
654 else {
655 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200658 }
659 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
660 if (global.spread_checks != 0) {
661 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT;
663 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200664 }
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200669 }
670 global.spread_checks = atol(args[1]);
671 if (global.spread_checks < 0 || global.spread_checks > 50) {
672 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200677 struct cfg_kw_list *kwl;
678 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200679 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200680
681 list_for_each_entry(kwl, &cfg_keywords.list, list) {
682 for (index = 0; kwl->kw[index].kw != NULL; index++) {
683 if (kwl->kw[index].section != CFG_GLOBAL)
684 continue;
685 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
686 /* prepare error message just in case */
687 snprintf(trash, sizeof(trash),
688 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200689 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
690 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200691 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200693 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200694 else if (rc > 0) {
695 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_WARN;
697 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200698 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200700 }
701 }
702 }
703
Willy Tarreaubaaee002006-06-26 02:48:02 +0200704 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200705 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 out:
708 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709}
710
711
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200712void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200713{
714 memset(&defproxy, 0, sizeof(defproxy));
715 defproxy.mode = PR_MODE_TCP;
716 defproxy.state = PR_STNEW;
717 defproxy.maxconn = cfg_maxpconn;
718 defproxy.conn_retries = CONN_RETRIES;
719 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200720
721 LIST_INIT(&defproxy.pendconns);
722 LIST_INIT(&defproxy.acl);
723 LIST_INIT(&defproxy.block_cond);
724 LIST_INIT(&defproxy.mon_fail_cond);
725 LIST_INIT(&defproxy.switching_rules);
726
Willy Tarreau3a70f942008-02-15 11:15:34 +0100727 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728}
729
730/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100731 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200732 * Returns the error code, 0 if OK, or any combination of :
733 * - ERR_ABORT: must abort ASAP
734 * - ERR_FATAL: we can continue parsing but not start the service
735 * - ERR_WARN: a warning has been emitted
736 * - ERR_ALERT: an alert has been emitted
737 * Only the two first ones can stop processing, the two others are just
738 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200740int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741{
742 static struct proxy *curproxy = NULL;
743 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200744 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100745 int rc;
746 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200747 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748
Willy Tarreau977b8e42006-12-29 14:19:17 +0100749 if (!strcmp(args[0], "listen"))
750 rc = PR_CAP_LISTEN;
751 else if (!strcmp(args[0], "frontend"))
752 rc = PR_CAP_FE | PR_CAP_RS;
753 else if (!strcmp(args[0], "backend"))
754 rc = PR_CAP_BE | PR_CAP_RS;
755 else if (!strcmp(args[0], "ruleset"))
756 rc = PR_CAP_RS;
757 else
758 rc = PR_CAP_NONE;
759
760 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 if (!*args[1]) {
762 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
763 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
764 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200765 err_code |= ERR_ALERT | ERR_ABORT;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200768
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100769 err = invalid_char(args[1]);
770 if (err) {
771 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
772 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100774 }
775
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200776 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
777 /*
778 * If there are two proxies with the same name only following
779 * combinations are allowed:
780 *
781 * listen backend frontend ruleset
782 * listen - - - -
783 * backend - - OK -
784 * frontend - OK - -
785 * ruleset - - - -
786 */
787
788 if (!strcmp(curproxy->id, args[1]) &&
789 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
790 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100791 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
792 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Willy Tarreau93893792009-07-23 13:19:11 +0200793 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200794 }
795 }
796
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
798 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200799 err_code |= ERR_ALERT | ERR_ABORT;
800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100802
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 curproxy->next = proxy;
804 proxy = curproxy;
805 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200806 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200807 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200808 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100809 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200810 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200811 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812
Willy Tarreauee991362007-05-14 14:37:50 +0200813 /* Timeouts are defined as -1, so we cannot use the zeroed area
814 * as a default value.
815 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100816 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200817
818 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100820 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821
822 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100823 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 curproxy->listen = str2listener(args[2], curproxy->listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200825 if (!curproxy->listen) {
826 err_code |= ERR_FATAL;
827 goto out;
828 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200829 global.maxsock++;
830 }
831
832 /* set default values */
833 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100835 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200836 curproxy->no_options = defproxy.no_options;
837 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100838 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100839 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200840 curproxy->except_net = defproxy.except_net;
841 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200842 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200843 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200845 if (defproxy.fwdfor_hdr_len) {
846 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
847 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
848 }
849
Willy Tarreau977b8e42006-12-29 14:19:17 +0100850 if (curproxy->cap & PR_CAP_FE) {
851 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100852 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200853 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100854
855 /* initialize error relocations */
856 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
857 if (defproxy.errmsg[rc].str)
858 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
859 }
860
861 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863
Willy Tarreau977b8e42006-12-29 14:19:17 +0100864 if (curproxy->cap & PR_CAP_BE) {
865 curproxy->fullconn = defproxy.fullconn;
866 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
Willy Tarreau977b8e42006-12-29 14:19:17 +0100868 if (defproxy.check_req)
869 curproxy->check_req = strdup(defproxy.check_req);
870 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871
Willy Tarreau977b8e42006-12-29 14:19:17 +0100872 if (defproxy.cookie_name)
873 curproxy->cookie_name = strdup(defproxy.cookie_name);
874 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100875
Emeric Brun647caf12009-06-30 17:57:00 +0200876 if (defproxy.rdp_cookie_name)
877 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
878 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
879
Willy Tarreau01732802007-11-01 22:48:15 +0100880 if (defproxy.url_param_name)
881 curproxy->url_param_name = strdup(defproxy.url_param_name);
882 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100883
Benoitaffb4812009-03-25 13:02:10 +0100884 if (defproxy.hh_name)
885 curproxy->hh_name = strdup(defproxy.hh_name);
886 curproxy->hh_len = defproxy.hh_len;
887 curproxy->hh_match_domain = defproxy.hh_match_domain;
888
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100889 if (defproxy.iface_name)
890 curproxy->iface_name = strdup(defproxy.iface_name);
891 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200894 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100895 if (defproxy.capture_name)
896 curproxy->capture_name = strdup(defproxy.capture_name);
897 curproxy->capture_namelen = defproxy.capture_namelen;
898 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900
Willy Tarreau977b8e42006-12-29 14:19:17 +0100901 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100902 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100903 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100904 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100905 curproxy->uri_auth = defproxy.uri_auth;
906 curproxy->mon_net = defproxy.mon_net;
907 curproxy->mon_mask = defproxy.mon_mask;
908 if (defproxy.monitor_uri)
909 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
910 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100911 if (defproxy.defbe.name)
912 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100913 }
914
915 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100916 curproxy->timeout.connect = defproxy.timeout.connect;
917 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100918 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100919 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100920 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +0200921 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100922 curproxy->source_addr = defproxy.source_addr;
923 }
924
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 curproxy->mode = defproxy.mode;
926 curproxy->logfac1 = defproxy.logfac1;
927 curproxy->logsrv1 = defproxy.logsrv1;
928 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200929 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 curproxy->logfac2 = defproxy.logfac2;
931 curproxy->logsrv2 = defproxy.logsrv2;
932 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200933 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100935 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
936 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200937
Willy Tarreau93893792009-07-23 13:19:11 +0200938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
940 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
941 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100942 /* FIXME-20070101: we should do this too at the end of the
943 * config parsing to free all default values.
944 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200945 free(defproxy.check_req);
946 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +0200947 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200948 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100949 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200950 free(defproxy.capture_name);
951 free(defproxy.monitor_uri);
952 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100953 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200954 free(defproxy.fwdfor_hdr_name);
955 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100956
Willy Tarreaua534fea2008-08-03 12:19:50 +0200957 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
958 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100959
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 /* we cannot free uri_auth because it might already be used */
961 init_default_instance();
962 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100963 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +0200964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966 else if (curproxy == NULL) {
967 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971
Willy Tarreau977b8e42006-12-29 14:19:17 +0100972
973 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100975 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100976 int cur_arg;
977
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 if (curproxy == &defproxy) {
979 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100983 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +0200984 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985
986 if (strchr(args[1], ':') == NULL) {
987 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200991 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100992
993 last_listen = curproxy->listen;
994 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200995 if (!curproxy->listen) {
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100999
1000 cur_arg = 2;
1001 while (*(args[cur_arg])) {
1002 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1003#ifdef SO_BINDTODEVICE
1004 struct listener *l;
1005
1006 if (!*args[cur_arg + 1]) {
1007 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001011 }
1012
1013 for (l = curproxy->listen; l != last_listen; l = l->next)
1014 l->interface = strdup(args[cur_arg + 1]);
1015
1016 global.last_checks |= LSTCHK_NETADM;
1017
1018 cur_arg += 2;
1019 continue;
1020#else
1021 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1022 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001025#endif
1026 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001027 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1028#ifdef TCP_MAXSEG
1029 struct listener *l;
1030 int mss;
1031
1032 if (!*args[cur_arg + 1]) {
1033 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001037 }
1038
1039 mss = str2uic(args[cur_arg + 1]);
1040 if (mss < 1 || mss > 65535) {
1041 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1042 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001045 }
1046
1047 for (l = curproxy->listen; l != last_listen; l = l->next)
1048 l->maxseg = mss;
1049
1050 cur_arg += 2;
1051 continue;
1052#else
1053 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1054 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001057#endif
1058 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001059 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001060#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001061 struct listener *l;
1062
1063 for (l = curproxy->listen; l != last_listen; l = l->next)
1064 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001065
1066 cur_arg ++;
1067 continue;
1068#else
1069 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1070 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001073#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001074 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001075 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 }
1083 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1084 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1085 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1086 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001090 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001092
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 /* flush useless bits */
1094 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001097 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001098 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001099 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001100
Willy Tarreau1c47f852006-07-09 08:22:27 +02001101 if (!*args[1]) {
1102 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001106 }
1107
Willy Tarreaua534fea2008-08-03 12:19:50 +02001108 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001109 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001110 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001111 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001112 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1113
Willy Tarreau93893792009-07-23 13:19:11 +02001114 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1117 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1118 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1119 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1120 else {
1121 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001126 else if (!strcmp(args[0], "id")) {
1127 struct proxy *target;
1128
1129 if (curproxy == &defproxy) {
1130 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001134 }
1135
1136 if (!*args[1]) {
1137 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001141 }
1142
1143 curproxy->uuid = atol(args[1]);
1144
1145 if (curproxy->uuid < 1001) {
1146 Alert("parsing [%s:%d]: custom id has to be > 1000",
1147 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001150 }
1151
1152 for (target = proxy; target; target = target->next)
1153 if (curproxy != target && curproxy->uuid == target->uuid) {
1154 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1155 file, linenum, curproxy->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02001156 err_code |= ERR_ALERT | ERR_FATAL;
1157 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001158 }
1159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1161 curproxy->state = PR_STSTOPPED;
1162 }
1163 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1164 curproxy->state = PR_STNEW;
1165 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001166 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1167 int cur_arg = 1;
1168 unsigned int set = 0;
1169
1170 while (*args[cur_arg]) {
1171 int u;
1172 if (strcmp(args[cur_arg], "all") == 0) {
1173 set = 0;
1174 break;
1175 }
1176 else if (strcmp(args[cur_arg], "odd") == 0) {
1177 set |= 0x55555555;
1178 }
1179 else if (strcmp(args[cur_arg], "even") == 0) {
1180 set |= 0xAAAAAAAA;
1181 }
1182 else {
1183 u = str2uic(args[cur_arg]);
1184 if (u < 1 || u > 32) {
1185 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001189 }
1190 if (u > global.nbproc) {
1191 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1192 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001193 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001194 }
1195 set |= 1 << (u - 1);
1196 }
1197 cur_arg++;
1198 }
1199 curproxy->bind_proc = set;
1200 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001201 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001202 if (curproxy == &defproxy) {
1203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001206 }
1207
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001208 err = invalid_char(args[1]);
1209 if (err) {
1210 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1211 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001213 }
1214
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001215 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1216 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1217 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001220 }
1221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1223 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001224
Willy Tarreau977b8e42006-12-29 14:19:17 +01001225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001227
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001234
1235 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 curproxy->cookie_name = strdup(args[1]);
1237 curproxy->cookie_len = strlen(curproxy->cookie_name);
1238
1239 cur_arg = 2;
1240 while (*(args[cur_arg])) {
1241 if (!strcmp(args[cur_arg], "rewrite")) {
1242 curproxy->options |= PR_O_COOK_RW;
1243 }
1244 else if (!strcmp(args[cur_arg], "indirect")) {
1245 curproxy->options |= PR_O_COOK_IND;
1246 }
1247 else if (!strcmp(args[cur_arg], "insert")) {
1248 curproxy->options |= PR_O_COOK_INS;
1249 }
1250 else if (!strcmp(args[cur_arg], "nocache")) {
1251 curproxy->options |= PR_O_COOK_NOC;
1252 }
1253 else if (!strcmp(args[cur_arg], "postonly")) {
1254 curproxy->options |= PR_O_COOK_POST;
1255 }
1256 else if (!strcmp(args[cur_arg], "prefix")) {
1257 curproxy->options |= PR_O_COOK_PFX;
1258 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001259 else if (!strcmp(args[cur_arg], "domain")) {
1260 if (!*args[cur_arg + 1]) {
1261 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1262 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001265 }
1266
1267 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1268 /* rfc2109, 4.3.2 Rejecting Cookies */
1269 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1270 " dots or does not start with a dot.\n",
1271 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001274 }
1275
1276 err = invalid_domainchar(args[cur_arg + 1]);
1277 if (err) {
1278 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1279 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001282 }
1283
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001284 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001285 cur_arg++;
1286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001288 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 }
1293 cur_arg++;
1294 }
1295 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1296 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1297 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 }
1300
1301 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1302 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1303 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001304 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305 }
1306 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001307 else if (!strcmp(args[0], "persist")) { /* persist */
1308 if (*(args[1]) == 0) {
1309 Alert("parsing [%s:%d] : missing persist method.\n",
1310 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001313 }
1314
1315 if (!strncmp(args[1], "rdp-cookie", 10)) {
1316 curproxy->options2 |= PR_O2_RDPC_PRST;
1317
1318 if (*(args[1] + 10 ) == '(') { /* cookie name */
1319 const char *beg, *end;
1320
1321 beg = args[1] + 11;
1322 end = strchr(beg, ')');
1323
1324 if (!end || end == beg) {
1325 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1326 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001329 }
1330
1331 free(curproxy->rdp_cookie_name);
1332 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1333 curproxy->rdp_cookie_len = end-beg;
1334 }
1335 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1336 free(curproxy->rdp_cookie_name);
1337 curproxy->rdp_cookie_name = strdup("msts");
1338 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1339 }
1340 else { /* syntax */
1341 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1342 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_FATAL;
1344 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001345 }
1346 }
1347 else {
1348 Alert("parsing [%s:%d] : unknown persist method.\n",
1349 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001350 err_code |= ERR_ALERT | ERR_FATAL;
1351 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001352 }
1353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355
Willy Tarreau977b8e42006-12-29 14:19:17 +01001356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001357 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001358
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 if (*(args[5]) == 0) {
1360 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1361 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 }
1365 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001366 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 curproxy->appsession_name = strdup(args[1]);
1368 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1369 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001370 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1371 if (err) {
1372 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1373 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001376 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001377 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001378
Willy Tarreau51041c72007-09-09 21:56:53 +02001379 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1380 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_ALERT | ERR_ABORT;
1382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384 } /* Url App Session */
1385 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001386 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001388
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 if (*(args[4]) == 0) {
1391 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001396 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 curproxy->capture_name = strdup(args[2]);
1398 curproxy->capture_namelen = strlen(curproxy->capture_name);
1399 curproxy->capture_len = atol(args[4]);
1400 if (curproxy->capture_len >= CAPTURE_LEN) {
1401 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1402 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 curproxy->capture_len = CAPTURE_LEN - 1;
1405 }
1406 curproxy->to_log |= LW_COOKIE;
1407 }
1408 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1409 struct cap_hdr *hdr;
1410
1411 if (curproxy == &defproxy) {
1412 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 }
1416
1417 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1418 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1419 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001420 err_code |= ERR_ALERT | ERR_FATAL;
1421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 }
1423
1424 hdr = calloc(sizeof(struct cap_hdr), 1);
1425 hdr->next = curproxy->req_cap;
1426 hdr->name = strdup(args[3]);
1427 hdr->namelen = strlen(args[3]);
1428 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001429 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 hdr->index = curproxy->nb_req_cap++;
1431 curproxy->req_cap = hdr;
1432 curproxy->to_log |= LW_REQHDR;
1433 }
1434 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1435 struct cap_hdr *hdr;
1436
1437 if (curproxy == &defproxy) {
1438 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001439 err_code |= ERR_ALERT | ERR_FATAL;
1440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 }
1442
1443 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1444 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1445 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
1449 hdr = calloc(sizeof(struct cap_hdr), 1);
1450 hdr->next = curproxy->rsp_cap;
1451 hdr->name = strdup(args[3]);
1452 hdr->namelen = strlen(args[3]);
1453 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001454 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 hdr->index = curproxy->nb_rsp_cap++;
1456 curproxy->rsp_cap = hdr;
1457 curproxy->to_log |= LW_RSPHDR;
1458 }
1459 else {
1460 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001462 err_code |= ERR_ALERT | ERR_FATAL;
1463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 }
1465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001468 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 if (*(args[1]) == 0) {
1471 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 }
1476 curproxy->conn_retries = atol(args[1]);
1477 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001478 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1479 int pol = ACL_COND_NONE;
1480 struct acl_cond *cond;
1481
Willy Tarreaub099aca2008-10-12 17:26:37 +02001482 if (curproxy == &defproxy) {
1483 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001484 err_code |= ERR_ALERT | ERR_FATAL;
1485 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001486 }
1487
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001488 if (!strcmp(args[1], "if"))
1489 pol = ACL_COND_IF;
1490 else if (!strcmp(args[1], "unless"))
1491 pol = ACL_COND_UNLESS;
1492
1493 if (pol == ACL_COND_NONE) {
1494 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1495 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001498 }
1499
1500 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1501 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001503 err_code |= ERR_ALERT | ERR_FATAL;
1504 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001505 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001506 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001507 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001508 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001509 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001510 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001511 else if (!strcmp(args[0], "redirect")) {
1512 int pol = ACL_COND_NONE;
1513 struct acl_cond *cond;
1514 struct redirect_rule *rule;
1515 int cur_arg;
1516 int type = REDIRECT_TYPE_NONE;
1517 int code = 302;
1518 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001519 char *cookie = NULL;
1520 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001521 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001522
1523 cur_arg = 1;
1524 while (*(args[cur_arg])) {
1525 if (!strcmp(args[cur_arg], "location")) {
1526 if (!*args[cur_arg + 1]) {
1527 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1528 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001531 }
1532
1533 type = REDIRECT_TYPE_LOCATION;
1534 cur_arg++;
1535 destination = args[cur_arg];
1536 }
1537 else if (!strcmp(args[cur_arg], "prefix")) {
1538 if (!*args[cur_arg + 1]) {
1539 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1540 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001541 err_code |= ERR_ALERT | ERR_FATAL;
1542 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001543 }
1544
1545 type = REDIRECT_TYPE_PREFIX;
1546 cur_arg++;
1547 destination = args[cur_arg];
1548 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001549 else if (!strcmp(args[cur_arg], "set-cookie")) {
1550 if (!*args[cur_arg + 1]) {
1551 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1552 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001555 }
1556
1557 cur_arg++;
1558 cookie = args[cur_arg];
1559 cookie_set = 1;
1560 }
1561 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1562 if (!*args[cur_arg + 1]) {
1563 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1564 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001567 }
1568
1569 cur_arg++;
1570 cookie = args[cur_arg];
1571 cookie_set = 0;
1572 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001573 else if (!strcmp(args[cur_arg],"code")) {
1574 if (!*args[cur_arg + 1]) {
1575 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001579 }
1580 cur_arg++;
1581 code = atol(args[cur_arg]);
1582 if (code < 301 || code > 303) {
1583 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1584 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001587 }
1588 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001589 else if (!strcmp(args[cur_arg],"drop-query")) {
1590 flags |= REDIRECT_FLAG_DROP_QS;
1591 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001592 else if (!strcmp(args[cur_arg], "if")) {
1593 pol = ACL_COND_IF;
1594 cur_arg++;
1595 break;
1596 }
1597 else if (!strcmp(args[cur_arg], "unless")) {
1598 pol = ACL_COND_UNLESS;
1599 cur_arg++;
1600 break;
1601 }
1602 else {
1603 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1604 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001607 }
1608 cur_arg++;
1609 }
1610
1611 if (type == REDIRECT_TYPE_NONE) {
1612 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001616 }
1617
1618 if (pol == ACL_COND_NONE) {
1619 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001621 err_code |= ERR_ALERT | ERR_FATAL;
1622 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001623 }
1624
1625 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001626 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001628 err_code |= ERR_ALERT | ERR_FATAL;
1629 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001630 }
1631
Willy Tarreaua9802632008-07-25 19:13:19 +02001632 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001633 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001634 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1635 rule->cond = cond;
1636 rule->rdr_str = strdup(destination);
1637 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001638 if (cookie) {
1639 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1640 * a clear consists in appending "; Max-Age=0" at the end.
1641 */
1642 rule->cookie_len = strlen(cookie);
1643 if (cookie_set)
1644 rule->cookie_str = strdup(cookie);
1645 else {
1646 rule->cookie_str = malloc(rule->cookie_len + 12);
1647 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1648 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1649 rule->cookie_len += 11;
1650 }
1651 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001652 rule->type = type;
1653 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001654 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001655 LIST_INIT(&rule->list);
1656 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001657 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001658 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001659 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001660 int pol = ACL_COND_NONE;
1661 struct acl_cond *cond;
1662 struct switching_rule *rule;
1663
Willy Tarreaub099aca2008-10-12 17:26:37 +02001664 if (curproxy == &defproxy) {
1665 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001666 err_code |= ERR_ALERT | ERR_FATAL;
1667 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001668 }
1669
Willy Tarreau55ea7572007-06-17 19:56:27 +02001670 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001672
1673 if (*(args[1]) == 0) {
1674 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001677 }
1678
1679 if (!strcmp(args[2], "if"))
1680 pol = ACL_COND_IF;
1681 else if (!strcmp(args[2], "unless"))
1682 pol = ACL_COND_UNLESS;
1683
1684 if (pol == ACL_COND_NONE) {
1685 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001689 }
1690
1691 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001692 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001693 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001696 }
1697
Willy Tarreaua9802632008-07-25 19:13:19 +02001698 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001699 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001700 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001701 struct acl *acl;
1702 const char *name;
1703
1704 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1705 name = acl ? acl->name : "(unknown)";
1706 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1707 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001708 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001709 }
1710
Willy Tarreau55ea7572007-06-17 19:56:27 +02001711 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1712 rule->cond = cond;
1713 rule->be.name = strdup(args[1]);
1714 LIST_INIT(&rule->list);
1715 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001718 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001719 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001720
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1722 curproxy->uri_auth = NULL; /* we must detach from the default config */
1723
1724 if (*(args[1]) == 0) {
Willy Tarreau1d45b7c2009-08-16 10:29:18 +02001725 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'node-name', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 } else if (!strcmp(args[1], "uri")) {
1729 if (*(args[2]) == 0) {
1730 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1734 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_ABORT;
1736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 }
1738 } else if (!strcmp(args[1], "realm")) {
1739 if (*(args[2]) == 0) {
1740 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1744 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001745 err_code |= ERR_ALERT | ERR_ABORT;
1746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +02001748 } else if (!strcmp(args[1], "node-name")) {
1749 if (!stats_set_node_name(&curproxy->uri_auth, *(args[2]) ? args[2] : hostname)) {
1750 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1751 err_code |= ERR_ALERT | ERR_ABORT;
1752 goto out;
1753 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001754 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001755 unsigned interval;
1756
1757 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1758 if (err) {
1759 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1760 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001763 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1764 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001765 err_code |= ERR_ALERT | ERR_ABORT;
1766 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 } else if (!strcmp(args[1], "auth")) {
1769 if (*(args[2]) == 0) {
1770 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1774 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001775 err_code |= ERR_ALERT | ERR_ABORT;
1776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 }
1778 } else if (!strcmp(args[1], "scope")) {
1779 if (*(args[2]) == 0) {
1780 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001783 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1784 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_ALERT | ERR_ABORT;
1786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 }
1788 } else if (!strcmp(args[1], "enable")) {
1789 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1790 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_ALERT | ERR_ABORT;
1792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001794 } else if (!strcmp(args[1], "hide-version")) {
1795 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1796 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001797 err_code |= ERR_ALERT | ERR_ABORT;
1798 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001801 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 }
1806 }
1807 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001808 int optnum;
1809
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001810 if (*(args[1]) == '\0') {
1811 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1812 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001816
1817 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1818 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001819 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1820 err_code |= ERR_WARN;
1821 goto out;
1822 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001823
Willy Tarreau3842f002009-06-14 11:39:52 +02001824 curproxy->no_options &= ~cfg_opts[optnum].val;
1825 curproxy->options &= ~cfg_opts[optnum].val;
1826
1827 switch (kwm) {
1828 case KWM_STD:
1829 curproxy->options |= cfg_opts[optnum].val;
1830 break;
1831 case KWM_NO:
1832 curproxy->no_options |= cfg_opts[optnum].val;
1833 break;
1834 case KWM_DEF: /* already cleared */
1835 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001836 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001837
Willy Tarreau93893792009-07-23 13:19:11 +02001838 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001839 }
1840 }
1841
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001842 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1843 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001844 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1845 err_code |= ERR_WARN;
1846 goto out;
1847 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001848
Willy Tarreau3842f002009-06-14 11:39:52 +02001849 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1850 curproxy->options2 &= ~cfg_opts2[optnum].val;
1851
1852 switch (kwm) {
1853 case KWM_STD:
1854 curproxy->options2 |= cfg_opts2[optnum].val;
1855 break;
1856 case KWM_NO:
1857 curproxy->no_options2 |= cfg_opts2[optnum].val;
1858 break;
1859 case KWM_DEF: /* already cleared */
1860 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001861 }
Willy Tarreau93893792009-07-23 13:19:11 +02001862 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001863 }
1864 }
1865
Willy Tarreau3842f002009-06-14 11:39:52 +02001866 if (kwm != KWM_STD) {
1867 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001868 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001871 }
1872
Emeric Brun3a058f32009-06-30 18:26:00 +02001873 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02001875 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02001877 if (*(args[2]) != '\0') {
1878 if (!strcmp(args[2], "clf")) {
1879 curproxy->options2 |= PR_O2_CLFLOG;
1880 } else {
1881 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001882 err_code |= ERR_ALERT | ERR_FATAL;
1883 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02001884 }
1885 }
1886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 else if (!strcmp(args[1], "tcplog"))
1888 /* generate a detailed TCP log */
1889 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 else if (!strcmp(args[1], "tcpka")) {
1891 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001892 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001894
1895 if (curproxy->cap & PR_CAP_FE)
1896 curproxy->options |= PR_O_TCP_CLI_KA;
1897 if (curproxy->cap & PR_CAP_BE)
1898 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 }
1900 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_WARN;
1903
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001905 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001906 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001907 curproxy->options &= ~PR_O_SMTP_CHK;
1908 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 if (!*args[2]) { /* no argument */
1910 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1911 curproxy->check_len = strlen(DEF_CHECK_REQ);
1912 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001913 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 curproxy->check_req = (char *)malloc(reqlen);
1915 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1916 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1917 } else { /* more arguments : METHOD URI [HTTP_VER] */
1918 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1919 if (*args[4])
1920 reqlen += strlen(args[4]);
1921 else
1922 reqlen += strlen("HTTP/1.0");
1923
1924 curproxy->check_req = (char *)malloc(reqlen);
1925 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1926 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1927 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001928 }
1929 else if (!strcmp(args[1], "ssl-hello-chk")) {
1930 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001933
Willy Tarreaua534fea2008-08-03 12:19:50 +02001934 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001935 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001936 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001937 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
Willy Tarreau23677902007-05-08 23:50:35 +02001939 else if (!strcmp(args[1], "smtpchk")) {
1940 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001941 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001942 curproxy->options &= ~PR_O_HTTP_CHK;
1943 curproxy->options &= ~PR_O_SSL3_CHK;
1944 curproxy->options |= PR_O_SMTP_CHK;
1945
1946 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1947 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1948 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1949 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1950 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1951 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1952 curproxy->check_req = (char *)malloc(reqlen);
1953 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1954 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1955 } else {
1956 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1957 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1958 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1959 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1960 }
1961 }
1962 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001963 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001964 int cur_arg;
1965
1966 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1967 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001968 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001969
1970 curproxy->options |= PR_O_FWDFOR;
1971
1972 free(curproxy->fwdfor_hdr_name);
1973 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1974 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1975
1976 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1977 cur_arg = 2;
1978 while (*(args[cur_arg])) {
1979 if (!strcmp(args[cur_arg], "except")) {
1980 /* suboption except - needs additional argument for it */
1981 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1982 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1983 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001986 }
1987 /* flush useless bits */
1988 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001989 cur_arg += 2;
1990 } else if (!strcmp(args[cur_arg], "header")) {
1991 /* suboption header - needs additional argument for it */
1992 if (*(args[cur_arg+1]) == 0) {
1993 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1994 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_ALERT | ERR_FATAL;
1996 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02001997 }
1998 free(curproxy->fwdfor_hdr_name);
1999 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2000 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2001 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002002 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002003 /* unknown suboption - catchall */
2004 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2005 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002008 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002009 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002010 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002011 else if (!strcmp(args[1], "originalto")) {
2012 int cur_arg;
2013
2014 /* insert x-original-to field, but not for the IP address listed as an except.
2015 * set default options (ie: bitfield, header name, etc)
2016 */
2017
2018 curproxy->options |= PR_O_ORGTO;
2019
2020 free(curproxy->orgto_hdr_name);
2021 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2022 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2023
2024 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2025 cur_arg = 2;
2026 while (*(args[cur_arg])) {
2027 if (!strcmp(args[cur_arg], "except")) {
2028 /* suboption except - needs additional argument for it */
2029 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2030 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2031 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002034 }
2035 /* flush useless bits */
2036 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2037 cur_arg += 2;
2038 } else if (!strcmp(args[cur_arg], "header")) {
2039 /* suboption header - needs additional argument for it */
2040 if (*(args[cur_arg+1]) == 0) {
2041 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2042 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_ALERT | ERR_FATAL;
2044 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002045 }
2046 free(curproxy->orgto_hdr_name);
2047 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2048 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2049 cur_arg += 2;
2050 } else {
2051 /* unknown suboption - catchall */
2052 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2053 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
2055 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002056 }
2057 } /* end while loop */
2058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 else {
2060 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
Willy Tarreau93893792009-07-23 13:19:11 +02002064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002066 else if (!strcmp(args[0], "default_backend")) {
2067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002069
2070 if (*(args[1]) == 0) {
2071 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002074 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002075 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002076 curproxy->defbe.name = strdup(args[1]);
2077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002082 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2083 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 /* enable reconnections to dispatch */
2086 curproxy->options |= PR_O_REDISP;
2087 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002088 else if (!strcmp(args[0], "http-check")) {
2089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002090 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002091
2092 if (strcmp(args[1], "disable-on-404") == 0) {
2093 /* enable a graceful server shutdown on an HTTP 404 response */
2094 curproxy->options |= PR_O_DISABLE404;
2095 }
2096 else {
2097 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002100 }
2101 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002102 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002107 }
2108
Willy Tarreaub80c2302007-11-30 20:51:32 +01002109 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002111
2112 if (strcmp(args[1], "fail") == 0) {
2113 /* add a condition to fail monitor requests */
2114 int pol = ACL_COND_NONE;
2115 struct acl_cond *cond;
2116
2117 if (!strcmp(args[2], "if"))
2118 pol = ACL_COND_IF;
2119 else if (!strcmp(args[2], "unless"))
2120 pol = ACL_COND_UNLESS;
2121
2122 if (pol == ACL_COND_NONE) {
2123 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2124 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002127 }
2128
2129 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2130 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2131 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002134 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002135 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002136 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002137 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2138 }
2139 else {
2140 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002143 }
2144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145#ifdef TPROXY
2146 else if (!strcmp(args[0], "transparent")) {
2147 /* enable transparent proxy connections */
2148 curproxy->options |= PR_O_TRANSP;
2149 }
2150#endif
2151 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002152 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 if (*(args[1]) == 0) {
2156 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 }
2160 curproxy->maxconn = atol(args[1]);
2161 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002162 else if (!strcmp(args[0], "backlog")) { /* backlog */
2163 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002165
2166 if (*(args[1]) == 0) {
2167 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002170 }
2171 curproxy->backlog = atol(args[1]);
2172 }
Willy Tarreau86034312006-12-29 00:10:33 +01002173 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002176
Willy Tarreau86034312006-12-29 00:10:33 +01002177 if (*(args[1]) == 0) {
2178 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002181 }
2182 curproxy->fullconn = atol(args[1]);
2183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2185 if (*(args[1]) == 0) {
2186 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002190 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2191 if (err) {
2192 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2193 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002196 }
2197 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
2199 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2200 if (curproxy == &defproxy) {
2201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002205 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 if (strchr(args[1], ':') == NULL) {
2209 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 }
2213 curproxy->dispatch_addr = *str2sa(args[1]);
2214 }
2215 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002217 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002219 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002220 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2221 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226 else if (!strcmp(args[0], "server")) { /* server address */
2227 int cur_arg;
2228 char *rport;
2229 char *raddr;
2230 short realport;
2231 int do_check;
2232
2233 if (curproxy == &defproxy) {
2234 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240
2241 if (!*args[2]) {
2242 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2243 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002247
2248 err = invalid_char(args[1]);
2249 if (err) {
2250 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2251 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002254 }
2255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2257 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_ABORT;
2259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
2261
2262 /* the servers are linked backwards first */
2263 newsrv->next = curproxy->srv;
2264 curproxy->srv = newsrv;
2265 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002266 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267
2268 LIST_INIT(&newsrv->pendconns);
2269 do_check = 0;
2270 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002271 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 newsrv->id = strdup(args[1]);
2273
2274 /* several ways to check the port component :
2275 * - IP => port=+0, relative
2276 * - IP: => port=+0, relative
2277 * - IP:N => port=N, absolute
2278 * - IP:+N => port=+N, relative
2279 * - IP:-N => port=-N, relative
2280 */
2281 raddr = strdup(args[2]);
2282 rport = strchr(raddr, ':');
2283 if (rport) {
2284 *rport++ = 0;
2285 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002286 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287 newsrv->state |= SRV_MAPPORTS;
2288 } else {
2289 realport = 0;
2290 newsrv->state |= SRV_MAPPORTS;
2291 }
2292
2293 newsrv->addr = *str2sa(raddr);
2294 newsrv->addr.sin_port = htons(realport);
2295 free(raddr);
2296
2297 newsrv->curfd = -1; /* no health-check in progress */
2298 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002299 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2300 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 newsrv->rise = DEF_RISETIME;
2302 newsrv->fall = DEF_FALLTIME;
2303 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002304 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002305 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002306 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002307
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 cur_arg = 3;
2309 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002310 if (!strcmp(args[cur_arg], "id")) {
2311 struct server *target;
2312
2313 if (!*args[cur_arg + 1]) {
2314 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2315 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002318 }
2319
2320 newsrv->puid = atol(args[cur_arg + 1]);
2321
2322 if (newsrv->puid< 1001) {
2323 Alert("parsing [%s:%d]: custom id has to be > 1000",
2324 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002327 }
2328
2329 for (target = proxy->srv; target; target = target->next)
2330 if (newsrv != target && newsrv->puid == target->puid) {
2331 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2332 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002335 }
2336 cur_arg += 2;
2337 }
2338 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 newsrv->cookie = strdup(args[cur_arg + 1]);
2340 newsrv->cklen = strlen(args[cur_arg + 1]);
2341 cur_arg += 2;
2342 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002343 else if (!strcmp(args[cur_arg], "redir")) {
2344 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2345 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2346 cur_arg += 2;
2347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 else if (!strcmp(args[cur_arg], "rise")) {
2349 newsrv->rise = atol(args[cur_arg + 1]);
2350 newsrv->health = newsrv->rise;
2351 cur_arg += 2;
2352 }
2353 else if (!strcmp(args[cur_arg], "fall")) {
2354 newsrv->fall = atol(args[cur_arg + 1]);
2355 cur_arg += 2;
2356 }
2357 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002358 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2359 if (err) {
2360 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2361 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002364 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002365 if (val <= 0) {
2366 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2367 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002370 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002371 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 cur_arg += 2;
2373 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002374 else if (!strcmp(args[cur_arg], "fastinter")) {
2375 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2376 if (err) {
2377 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2378 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002381 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002382 if (val <= 0) {
2383 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2384 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002387 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002388 newsrv->fastinter = val;
2389 cur_arg += 2;
2390 }
2391 else if (!strcmp(args[cur_arg], "downinter")) {
2392 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2393 if (err) {
2394 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2395 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002398 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002399 if (val <= 0) {
2400 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2401 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002404 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002405 newsrv->downinter = val;
2406 cur_arg += 2;
2407 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002408 else if (!strcmp(args[cur_arg], "addr")) {
2409 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002410 cur_arg += 2;
2411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 else if (!strcmp(args[cur_arg], "port")) {
2413 newsrv->check_port = atol(args[cur_arg + 1]);
2414 cur_arg += 2;
2415 }
2416 else if (!strcmp(args[cur_arg], "backup")) {
2417 newsrv->state |= SRV_BACKUP;
2418 cur_arg ++;
2419 }
2420 else if (!strcmp(args[cur_arg], "weight")) {
2421 int w;
2422 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002423 if (w < 0 || w > 256) {
2424 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002429 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 cur_arg += 2;
2431 }
2432 else if (!strcmp(args[cur_arg], "minconn")) {
2433 newsrv->minconn = atol(args[cur_arg + 1]);
2434 cur_arg += 2;
2435 }
2436 else if (!strcmp(args[cur_arg], "maxconn")) {
2437 newsrv->maxconn = atol(args[cur_arg + 1]);
2438 cur_arg += 2;
2439 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002440 else if (!strcmp(args[cur_arg], "maxqueue")) {
2441 newsrv->maxqueue = atol(args[cur_arg + 1]);
2442 cur_arg += 2;
2443 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002444 else if (!strcmp(args[cur_arg], "slowstart")) {
2445 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002446 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002447 if (err) {
2448 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2449 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002452 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002453 if (val <= 0) {
2454 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2455 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002458 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002459 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002460 cur_arg += 2;
2461 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002462 else if (!strcmp(args[cur_arg], "track")) {
2463
2464 if (!*args[cur_arg + 1]) {
2465 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2466 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002469 }
2470
2471 newsrv->trackit = strdup(args[cur_arg + 1]);
2472
2473 cur_arg += 2;
2474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 else if (!strcmp(args[cur_arg], "check")) {
2476 global.maxsock++;
2477 do_check = 1;
2478 cur_arg += 1;
2479 }
2480 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002481 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002483#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002484 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002485 file, linenum, "source", "usesrc");
2486#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002489#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
2493 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002494 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2495
2496 if (port_low != port_high) {
2497 int i;
2498 if (port_low <= 0 || port_low > 65535 ||
2499 port_high <= 0 || port_high > 65535 ||
2500 port_low > port_high) {
2501 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2502 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002505 }
2506 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2507 for (i = 0; i < newsrv->sport_range->size; i++)
2508 newsrv->sport_range->ports[i] = port_low + i;
2509 }
2510
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002512 while (*(args[cur_arg])) {
2513 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002514#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2515#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002516 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2517 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2518 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002521 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002522#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002523 if (!*args[cur_arg + 1]) {
2524 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2525 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002528 }
2529 if (!strcmp(args[cur_arg + 1], "client")) {
2530 newsrv->state |= SRV_TPROXY_CLI;
2531 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2532 newsrv->state |= SRV_TPROXY_CIP;
2533 } else {
2534 newsrv->state |= SRV_TPROXY_ADDR;
2535 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2536 }
2537 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002538#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002539 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002540#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002541 cur_arg += 2;
2542 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002543#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002544 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002545 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002548#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2549 } /* "usesrc" */
2550
2551 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2552#ifdef SO_BINDTODEVICE
2553 if (!*args[cur_arg + 1]) {
2554 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2555 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002558 }
2559 if (newsrv->iface_name)
2560 free(newsrv->iface_name);
2561
2562 newsrv->iface_name = strdup(args[cur_arg + 1]);
2563 newsrv->iface_len = strlen(newsrv->iface_name);
2564 global.last_checks |= LSTCHK_NETADM;
2565#else
2566 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2567 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002570#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002571 cur_arg += 2;
2572 continue;
2573 }
2574 /* this keyword in not an option of "source" */
2575 break;
2576 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002578 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2579 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2580 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002585 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 +02002586 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
2590 }
2591
2592 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002593 if (newsrv->trackit) {
2594 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2595 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002598 }
2599
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002600 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2601 newsrv->check_port = newsrv->check_addr.sin_port;
2602
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2604 newsrv->check_port = realport; /* by default */
2605 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002606 /* not yet valid, because no port was set on
2607 * the server either. We'll check if we have
2608 * a known port on the first listener.
2609 */
2610 struct listener *l;
2611 l = curproxy->listen;
2612 if (l) {
2613 int port;
2614 port = (l->addr.ss_family == AF_INET6)
2615 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2616 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2617 newsrv->check_port = port;
2618 }
2619 }
2620 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2622 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 }
2626 newsrv->state |= SRV_CHECKED;
2627 }
2628
2629 if (newsrv->state & SRV_BACKUP)
2630 curproxy->srv_bck++;
2631 else
2632 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002633
2634 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635 }
2636 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002637 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 int facility;
2639
2640 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2641 curproxy->logfac1 = global.logfac1;
2642 curproxy->logsrv1 = global.logsrv1;
2643 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002644 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 curproxy->logfac2 = global.logfac2;
2646 curproxy->logsrv2 = global.logsrv2;
2647 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002648 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
2650 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002651 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002652
2653 facility = get_log_facility(args[2]);
2654 if (facility < 0) {
2655 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2656 exit(1);
2657 }
2658
2659 level = 7; /* max syslog level = debug */
2660 if (*(args[3])) {
2661 level = get_log_level(args[3]);
2662 if (level < 0) {
2663 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2664 exit(1);
2665 }
2666 }
2667
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002668 minlvl = 0; /* limit syslog level to this level (emerg) */
2669 if (*(args[4])) {
2670 minlvl = get_log_level(args[4]);
2671 if (level < 0) {
2672 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2673 exit(1);
2674 }
2675 }
2676
Robert Tsai81ae1952007-12-05 10:47:29 +01002677 if (args[1][0] == '/') {
2678 logsrv.u.addr.sa_family = AF_UNIX;
2679 logsrv.u.un = *str2sun(args[1]);
2680 } else {
2681 logsrv.u.addr.sa_family = AF_INET;
2682 logsrv.u.in = *str2sa(args[1]);
2683 if (!logsrv.u.in.sin_port) {
2684 logsrv.u.in.sin_port =
2685 htons(SYSLOG_PORT);
2686 }
2687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688
2689 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002690 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 curproxy->logfac1 = facility;
2692 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002693 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
2695 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002696 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 curproxy->logfac2 = facility;
2698 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002699 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
2701 else {
2702 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
2706 }
2707 else {
2708 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2709 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 }
2713 }
2714 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002715 int cur_arg;
2716
Willy Tarreau977b8e42006-12-29 14:19:17 +01002717 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002719
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002721 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2722 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002726
2727 /* we must first clear any optional default setting */
2728 curproxy->options &= ~PR_O_TPXY_MASK;
2729 free(curproxy->iface_name);
2730 curproxy->iface_name = NULL;
2731 curproxy->iface_len = 0;
2732
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733 curproxy->source_addr = *str2sa(args[1]);
2734 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002735
2736 cur_arg = 2;
2737 while (*(args[cur_arg])) {
2738 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002739#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2740#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002741 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2742 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2743 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002746 }
2747#endif
2748 if (!*args[cur_arg + 1]) {
2749 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2750 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002753 }
2754
2755 if (!strcmp(args[cur_arg + 1], "client")) {
2756 curproxy->options |= PR_O_TPXY_CLI;
2757 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2758 curproxy->options |= PR_O_TPXY_CIP;
2759 } else {
2760 curproxy->options |= PR_O_TPXY_ADDR;
2761 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2762 }
2763 global.last_checks |= LSTCHK_NETADM;
2764#if !defined(CONFIG_HAP_LINUX_TPROXY)
2765 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002766#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002767#else /* no TPROXY support */
2768 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002769 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002772#endif
2773 cur_arg += 2;
2774 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002775 }
2776
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002777 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2778#ifdef SO_BINDTODEVICE
2779 if (!*args[cur_arg + 1]) {
2780 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002784 }
2785 if (curproxy->iface_name)
2786 free(curproxy->iface_name);
2787
2788 curproxy->iface_name = strdup(args[cur_arg + 1]);
2789 curproxy->iface_len = strlen(curproxy->iface_name);
2790 global.last_checks |= LSTCHK_NETADM;
2791#else
2792 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2793 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002796#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002797 cur_arg += 2;
2798 continue;
2799 }
2800 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2801 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002804 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002805 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002806 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2807 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2808 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2813 regex_t *preg;
2814 if (curproxy == &defproxy) {
2815 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002819 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002821
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 if (*(args[1]) == 0 || *(args[2]) == 0) {
2823 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2824 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
2828
2829 preg = calloc(1, sizeof(regex_t));
2830 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2831 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 }
2835
2836 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2837 if (err) {
2838 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2839 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002842 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002843 }
2844 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2845 regex_t *preg;
2846 if (curproxy == &defproxy) {
2847 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002853
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 if (*(args[1]) == 0) {
2855 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002858 }
2859
2860 preg = calloc(1, sizeof(regex_t));
2861 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2862 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002863 err_code |= ERR_ALERT | ERR_FATAL;
2864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 }
2866
2867 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002868 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 }
2870 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2871 regex_t *preg;
2872 if (curproxy == &defproxy) {
2873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002877 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002879
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 if (*(args[1]) == 0) {
2881 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
2885
2886 preg = calloc(1, sizeof(regex_t));
2887 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2888 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002891 }
2892
2893 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002894 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895 }
2896 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2897 regex_t *preg;
2898 if (curproxy == &defproxy) {
2899 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002903 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002904 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002905
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906 if (*(args[1]) == 0) {
2907 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 }
2911
2912 preg = calloc(1, sizeof(regex_t));
2913 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2914 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917 }
2918
2919 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002920 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 }
2922 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2923 regex_t *preg;
2924 if (curproxy == &defproxy) {
2925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002929 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002930 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002931
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 if (*(args[1]) == 0) {
2933 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 }
2937
2938 preg = calloc(1, sizeof(regex_t));
2939 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2940 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002943 }
2944
2945 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002946 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002948 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2949 regex_t *preg;
2950 if (curproxy == &defproxy) {
2951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002955 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002957
Willy Tarreaub8750a82006-09-03 09:56:00 +02002958 if (*(args[1]) == 0) {
2959 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002962 }
2963
2964 preg = calloc(1, sizeof(regex_t));
2965 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2966 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002969 }
2970
2971 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002972 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002973 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002974 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2975 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01002983
Willy Tarreau977b8e42006-12-29 14:19:17 +01002984 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002985 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2986 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002989 }
2990
2991 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002992 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002993 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01002996 }
2997
2998 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002999 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003000 }
3001 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3002 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003003 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003004 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003007 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003008 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003010
Willy Tarreau977b8e42006-12-29 14:19:17 +01003011 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003012 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003016 }
3017
3018 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003019 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003020 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003023 }
3024
3025 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003026 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3029 regex_t *preg;
3030 if (curproxy == &defproxy) {
3031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003035 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003037
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 if (*(args[1]) == 0 || *(args[2]) == 0) {
3039 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 }
3044
3045 preg = calloc(1, sizeof(regex_t));
3046 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3047 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051
3052 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3053 if (err) {
3054 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3055 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003059 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
3061 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3062 regex_t *preg;
3063 if (curproxy == &defproxy) {
3064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003068 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 if (*(args[1]) == 0) {
3072 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
3076
3077 preg = calloc(1, sizeof(regex_t));
3078 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3079 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
3083
3084 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003085 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 }
3087 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3088 regex_t *preg;
3089 if (curproxy == &defproxy) {
3090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003094 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003096
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 if (*(args[1]) == 0) {
3098 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 }
3102
3103 preg = calloc(1, sizeof(regex_t));
3104 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3105 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
3109
3110 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003111 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 }
3113 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3114 regex_t *preg;
3115 if (curproxy == &defproxy) {
3116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003120 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 if (*(args[1]) == 0) {
3124 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
3128
3129 preg = calloc(1, sizeof(regex_t));
3130 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3131 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 }
3135
3136 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003137 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 }
3139 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3140 regex_t *preg;
3141 if (curproxy == &defproxy) {
3142 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003146 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003148
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 if (*(args[1]) == 0) {
3150 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
3154
3155 preg = calloc(1, sizeof(regex_t));
3156 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3157 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 }
3161
3162 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003163 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003165 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3166 regex_t *preg;
3167 if (curproxy == &defproxy) {
3168 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003171 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003172 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003174
Willy Tarreaub8750a82006-09-03 09:56:00 +02003175 if (*(args[1]) == 0) {
3176 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003179 }
3180
3181 preg = calloc(1, sizeof(regex_t));
3182 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3183 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003186 }
3187
3188 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003189 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3192 if (curproxy == &defproxy) {
3193 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003197 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199
3200 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3201 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
3205
3206 if (*(args[1]) == 0) {
3207 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
3211
3212 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003213 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
3215 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3216 regex_t *preg;
3217
3218 if (*(args[1]) == 0 || *(args[2]) == 0) {
3219 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003224 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 preg = calloc(1, sizeof(regex_t));
3228 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3229 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 }
3233
3234 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3235 if (err) {
3236 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3237 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003241 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
3243 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3244 regex_t *preg;
3245 if (curproxy == &defproxy) {
3246 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003250 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003252
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 if (*(args[1]) == 0) {
3254 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
3258
3259 preg = calloc(1, sizeof(regex_t));
3260 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3261 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 }
3265
3266 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3267 if (err) {
3268 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3269 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
3273 }
3274 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3275 regex_t *preg;
3276 if (curproxy == &defproxy) {
3277 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003281 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003283
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 if (*(args[1]) == 0) {
3285 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
3289
3290 preg = calloc(1, sizeof(regex_t));
3291 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3292 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296
3297 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3298 if (err) {
3299 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3300 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
3304 }
3305 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3306 regex_t *preg;
3307 if (curproxy == &defproxy) {
3308 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003312 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314
3315 if (*(args[1]) == 0 || *(args[2]) == 0) {
3316 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
3321
3322 preg = calloc(1, sizeof(regex_t));
3323 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3324 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328
3329 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3330 if (err) {
3331 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3332 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
3336 }
3337 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3338 regex_t *preg;
3339 if (curproxy == &defproxy) {
3340 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003344 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003346
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 if (*(args[1]) == 0) {
3348 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
3352
3353 preg = calloc(1, sizeof(regex_t));
3354 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3355 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 }
3359
3360 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3361 if (err) {
3362 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3363 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
3367 }
3368 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3369 regex_t *preg;
3370 if (curproxy == &defproxy) {
3371 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003375 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003377
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 if (*(args[1]) == 0) {
3379 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383
3384 preg = calloc(1, sizeof(regex_t));
3385 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3386 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
3390
3391 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3392 if (err) {
3393 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3394 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_ALERT | ERR_FATAL;
3396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 }
3398 }
3399 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3400 if (curproxy == &defproxy) {
3401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003405 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003407
3408 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3409 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413
3414 if (*(args[1]) == 0) {
3415 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419
3420 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3421 }
3422 else if (!strcmp(args[0], "errorloc") ||
3423 !strcmp(args[0], "errorloc302") ||
3424 !strcmp(args[0], "errorloc303")) { /* error location */
3425 int errnum, errlen;
3426 char *err;
3427
Willy Tarreau977b8e42006-12-29 14:19:17 +01003428 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003430
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003432 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
3436
3437 errnum = atol(args[1]);
3438 if (!strcmp(args[0], "errorloc303")) {
3439 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3440 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3441 } else {
3442 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3443 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3444 }
3445
Willy Tarreau0f772532006-12-23 20:51:41 +01003446 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3447 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003448 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003449 curproxy->errmsg[rc].str = err;
3450 curproxy->errmsg[rc].len = errlen;
3451 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003454
3455 if (rc >= HTTP_ERR_SIZE) {
3456 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3457 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 free(err);
3459 }
3460 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003461 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3462 int errnum, errlen, fd;
3463 char *err;
3464 struct stat stat;
3465
3466 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003467 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003468
3469 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003470 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003473 }
3474
3475 fd = open(args[2], O_RDONLY);
3476 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3477 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3478 file, linenum, args[2], args[1]);
3479 if (fd >= 0)
3480 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003483 }
3484
3485 if (stat.st_size <= BUFSIZE) {
3486 errlen = stat.st_size;
3487 } else {
3488 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3489 file, linenum, args[2], BUFSIZE);
Willy Tarreau93893792009-07-23 13:19:11 +02003490 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003491 errlen = BUFSIZE;
3492 }
3493
3494 err = malloc(errlen); /* malloc() must succeed during parsing */
3495 errnum = read(fd, err, errlen);
3496 if (errnum != errlen) {
3497 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3498 file, linenum, args[2], args[1]);
3499 close(fd);
3500 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003503 }
3504 close(fd);
3505
3506 errnum = atol(args[1]);
3507 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3508 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003509 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003510 curproxy->errmsg[rc].str = err;
3511 curproxy->errmsg[rc].len = errlen;
3512 break;
3513 }
3514 }
3515
3516 if (rc >= HTTP_ERR_SIZE) {
3517 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3518 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003519 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003520 free(err);
3521 }
3522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003524 struct cfg_kw_list *kwl;
3525 int index;
3526
3527 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3528 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3529 if (kwl->kw[index].section != CFG_LISTEN)
3530 continue;
3531 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3532 /* prepare error message just in case */
3533 snprintf(trash, sizeof(trash),
3534 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003535 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3536 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003537 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003540 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003541 else if (rc > 0) {
3542 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_WARN;
3544 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003545 }
Willy Tarreau93893792009-07-23 13:19:11 +02003546 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003547 }
3548 }
3549 }
3550
Willy Tarreau6daf3432008-01-22 16:44:08 +01003551 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Willy Tarreau93893792009-07-23 13:19:11 +02003555 out:
3556 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557}
3558
3559
3560/*
3561 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003562 * Returns the error code, 0 if OK, or any combination of :
3563 * - ERR_ABORT: must abort ASAP
3564 * - ERR_FATAL: we can continue parsing but not start the service
3565 * - ERR_WARN: a warning has been emitted
3566 * - ERR_ALERT: an alert has been emitted
3567 * Only the two first ones can stop processing, the two others are just
3568 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003570int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003572 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 FILE *f;
3574 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003576 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 if ((f=fopen(file,"r")) == NULL)
3579 return -1;
3580
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003581 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003582 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003583 char *end;
3584 char *args[MAX_LINE_ARGS + 1];
3585 char *line = thisline;
3586
Willy Tarreaubaaee002006-06-26 02:48:02 +02003587 linenum++;
3588
3589 end = line + strlen(line);
3590
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003591 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3592 /* Check if we reached the limit and the last char is not \n.
3593 * Watch out for the last line without the terminating '\n'!
3594 */
3595 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003596 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003598 }
3599
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003601 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 line++;
3603
3604 arg = 0;
3605 args[arg] = line;
3606
3607 while (*line && arg < MAX_LINE_ARGS) {
3608 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3609 * C equivalent value. Other combinations left unchanged (eg: \1).
3610 */
3611 if (*line == '\\') {
3612 int skip = 0;
3613 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3614 *line = line[1];
3615 skip = 1;
3616 }
3617 else if (line[1] == 'r') {
3618 *line = '\r';
3619 skip = 1;
3620 }
3621 else if (line[1] == 'n') {
3622 *line = '\n';
3623 skip = 1;
3624 }
3625 else if (line[1] == 't') {
3626 *line = '\t';
3627 skip = 1;
3628 }
3629 else if (line[1] == 'x') {
3630 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3631 unsigned char hex1, hex2;
3632 hex1 = toupper(line[2]) - '0';
3633 hex2 = toupper(line[3]) - '0';
3634 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3635 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3636 *line = (hex1<<4) + hex2;
3637 skip = 3;
3638 }
3639 else {
3640 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
3643 }
3644 if (skip) {
3645 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3646 end -= skip;
3647 }
3648 line++;
3649 }
3650 else if (*line == '#' || *line == '\n' || *line == '\r') {
3651 /* end of string, end of loop */
3652 *line = 0;
3653 break;
3654 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003655 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003657 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003658 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 line++;
3660 args[++arg] = line;
3661 }
3662 else {
3663 line++;
3664 }
3665 }
3666
3667 /* empty line */
3668 if (!**args)
3669 continue;
3670
Willy Tarreau540abe42007-05-02 20:50:16 +02003671 /* zero out remaining args and ensure that at least one entry
3672 * is zeroed out.
3673 */
3674 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 args[arg] = line;
3676 }
3677
Willy Tarreau3842f002009-06-14 11:39:52 +02003678 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003679 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003680 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003681 for (arg=0; *args[arg+1]; arg++)
3682 args[arg] = args[arg+1]; // shift args after inversion
3683 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003684 else if (!strcmp(args[0], "default")) {
3685 kwm = KWM_DEF;
3686 for (arg=0; *args[arg+1]; arg++)
3687 args[arg] = args[arg+1]; // shift args after inversion
3688 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003689
Willy Tarreau3842f002009-06-14 11:39:52 +02003690 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3691 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003693 }
3694
Willy Tarreau977b8e42006-12-29 14:19:17 +01003695 if (!strcmp(args[0], "listen") ||
3696 !strcmp(args[0], "frontend") ||
3697 !strcmp(args[0], "backend") ||
3698 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003699 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003701 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003702 cursection = strdup(args[0]);
3703 }
3704 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003706 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003707 cursection = strdup(args[0]);
3708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 /* else it's a section keyword */
3710
3711 switch (confsect) {
3712 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 break;
3715 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003716 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 break;
3718 default:
3719 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003722
3723 if (err_code & ERR_ABORT)
3724 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003726 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003727 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003729 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003730}
3731
Willy Tarreaubb925012009-07-23 13:36:36 +02003732/*
3733 * Returns the error code, 0 if OK, or any combination of :
3734 * - ERR_ABORT: must abort ASAP
3735 * - ERR_FATAL: we can continue parsing but not start the service
3736 * - ERR_WARN: a warning has been emitted
3737 * - ERR_ALERT: an alert has been emitted
3738 * Only the two first ones can stop processing, the two others are just
3739 * indicators.
3740 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003741int check_config_validity()
3742{
3743 int cfgerr = 0;
3744 struct proxy *curproxy = NULL;
3745 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003746 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747
3748 /*
3749 * Now, check for the integrity of all that we have collected.
3750 */
3751
3752 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003753 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003754
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003755 /* first, we will invert the proxy list order */
3756 curproxy = NULL;
3757 while (proxy) {
3758 struct proxy *next;
3759
3760 next = proxy->next;
3761 proxy->next = curproxy;
3762 curproxy = proxy;
3763 if (!next)
3764 break;
3765 proxy = next;
3766 }
3767
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003769 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 }
3773
3774 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003775 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003776 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003777
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003779 /* ensure we don't keep listeners uselessly bound */
3780 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 curproxy = curproxy->next;
3782 continue;
3783 }
3784
Willy Tarreauff01a212009-03-15 13:46:16 +01003785 switch (curproxy->mode) {
3786 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003787 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003788 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003789 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3790 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003791 cfgerr++;
3792 }
3793
3794 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003795 Warning("config : servers will be ignored for %s '%s'.\n",
3796 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003797 break;
3798
3799 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003800 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003801 break;
3802
3803 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003804 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003805 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003806 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3807 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003808 cfgerr++;
3809 }
3810 break;
3811 }
3812
3813 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003814 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3815 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 cfgerr++;
3817 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003818
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003819 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3820 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3821 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003822 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
3823 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003824 cfgerr++;
3825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003827 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003828 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3829 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003830 cfgerr++;
3831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003833 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003834 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3835 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003836 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003837 }
3838 }
3839 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3840 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3841 /* If no LB algo is set in a backend, and we're not in
3842 * transparent mode, dispatch mode nor proxy mode, we
3843 * want to use balance roundrobin by default.
3844 */
3845 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3846 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 }
3848 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003849
Willy Tarreau82936582007-11-30 15:20:09 +01003850 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3851 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003852 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3853 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003854 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01003855 }
3856
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003857 /* if a default backend was specified, let's find it */
3858 if (curproxy->defbe.name) {
3859 struct proxy *target;
3860
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003861 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3862 if (!target) {
3863 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3864 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003865 cfgerr++;
3866 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003867 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3868 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02003869 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003870 } else {
3871 free(curproxy->defbe.name);
3872 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003873 /* we force the backend to be present on at least all of
3874 * the frontend's processes.
3875 */
3876 target->bind_proc = curproxy->bind_proc ?
3877 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
3879 }
3880
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003881 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003882 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3883 /* map jump target for ACT_SETBE in req_rep chain */
3884 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003885 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003886 struct proxy *target;
3887
Willy Tarreaua496b602006-12-17 23:15:24 +01003888 if (exp->action != ACT_SETBE)
3889 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003890
3891 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3892 if (!target) {
3893 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3894 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003895 cfgerr++;
3896 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003897 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3898 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003899 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003900 } else {
3901 free((void *)exp->replace);
3902 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003903 /* we force the backend to be present on at least all of
3904 * the frontend's processes.
3905 */
3906 target->bind_proc = curproxy->bind_proc ?
3907 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003908 }
3909 }
3910 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003911
3912 /* find the target proxy for 'use_backend' rules */
3913 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003914 struct proxy *target;
3915
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003916 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003917
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003918 if (!target) {
3919 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3920 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003921 cfgerr++;
3922 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003923 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3924 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003925 cfgerr++;
3926 } else {
3927 free((void *)rule->be.name);
3928 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003929 /* we force the backend to be present on at least all of
3930 * the frontend's processes.
3931 */
3932 target->bind_proc = curproxy->bind_proc ?
3933 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003934 }
3935 }
3936
Willy Tarreau2738a142006-07-08 17:28:09 +02003937 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003938 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003939 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003940 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003941 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003942 " | While not properly invalid, you will certainly encounter various problems\n"
3943 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003944 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003945 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003946 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02003947 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003948
Willy Tarreau1fa31262007-12-03 00:36:16 +01003949 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3950 * We must still support older configurations, so let's find out whether those
3951 * parameters have been set or must be copied from contimeouts.
3952 */
3953 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003954 if (!curproxy->timeout.tarpit ||
3955 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003956 /* tarpit timeout not set. We search in the following order:
3957 * default.tarpit, curr.connect, default.connect.
3958 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003959 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003960 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003961 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003962 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003963 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003964 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003965 }
3966 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003967 (!curproxy->timeout.queue ||
3968 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003969 /* queue timeout not set. We search in the following order:
3970 * default.queue, curr.connect, default.connect.
3971 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003972 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003973 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003974 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003975 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003976 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003977 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003978 }
3979 }
3980
Willy Tarreauf3c69202006-07-09 16:42:34 +02003981 if (curproxy->options & PR_O_SSL3_CHK) {
3982 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3983 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3984 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3985 }
3986
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003987 /* The small pools required for the capture lists */
3988 if (curproxy->nb_req_cap)
3989 curproxy->req_cap_pool = create_pool("ptrcap",
3990 curproxy->nb_req_cap * sizeof(char *),
3991 MEM_F_SHARED);
3992 if (curproxy->nb_rsp_cap)
3993 curproxy->rsp_cap_pool = create_pool("ptrcap",
3994 curproxy->nb_rsp_cap * sizeof(char *),
3995 MEM_F_SHARED);
3996
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003997 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3998 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3999 MEM_F_SHARED);
4000
Willy Tarreau86034312006-12-29 00:10:33 +01004001 /* for backwards compatibility with "listen" instances, if
4002 * fullconn is not set but maxconn is set, then maxconn
4003 * is used.
4004 */
4005 if (!curproxy->fullconn)
4006 curproxy->fullconn = curproxy->maxconn;
4007
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 /* first, we will invert the servers list order */
4009 newsrv = NULL;
4010 while (curproxy->srv) {
4011 struct server *next;
4012
4013 next = curproxy->srv->next;
4014 curproxy->srv->next = newsrv;
4015 newsrv = curproxy->srv;
4016 if (!next)
4017 break;
4018 curproxy->srv = next;
4019 }
4020
Willy Tarreau20697042007-11-15 23:26:18 +01004021 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004022 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023
Willy Tarreaub625a082007-11-26 01:15:43 +01004024 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01004025 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01004026 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01004027 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
4028 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01004029 else
4030 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031
4032 if (curproxy->options & PR_O_LOGASAP)
4033 curproxy->to_log &= ~LW_BYTES;
4034
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004035 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4036 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4037 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4038 proxy_type_str(curproxy), curproxy->id);
4039 err_code |= ERR_WARN;
4040 }
4041
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004043 * ensure that we're not cross-dressing a TCP server into HTTP.
4044 */
4045 newsrv = curproxy->srv;
4046 while (newsrv != NULL) {
4047 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004048 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4049 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004050 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004051 }
4052 newsrv = newsrv->next;
4053 }
4054
4055 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 * If this server supports a maxconn parameter, it needs a dedicated
4057 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004058 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 */
4060 newsrv = curproxy->srv;
4061 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004062 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 /* Only 'minconn' was specified, or it was higher than or equal
4064 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4065 * this will avoid further useless expensive computations.
4066 */
4067 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004068 } else if (newsrv->maxconn && !newsrv->minconn) {
4069 /* minconn was not specified, so we set it to maxconn */
4070 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004071 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004072 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4073 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004074 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 }
4076
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004077 if (newsrv->trackit) {
4078 struct proxy *px;
4079 struct server *srv;
4080 char *pname, *sname;
4081
4082 pname = newsrv->trackit;
4083 sname = strrchr(pname, '/');
4084
4085 if (sname)
4086 *sname++ = '\0';
4087 else {
4088 sname = pname;
4089 pname = NULL;
4090 }
4091
4092 if (pname) {
4093 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4094 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004095 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4096 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004097 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004098 cfgerr++;
4099 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004100 }
4101 } else
4102 px = curproxy;
4103
4104 srv = findserver(px, sname);
4105 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004106 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4107 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004108 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004109 cfgerr++;
4110 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004111 }
4112
4113 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004114 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004115 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004116 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004117 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004118 cfgerr++;
4119 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004120 }
4121
4122 if (curproxy != px &&
4123 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004124 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004125 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004126 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004127 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004128 cfgerr++;
4129 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004130 }
4131
4132 newsrv->tracked = srv;
4133 newsrv->tracknext = srv->tracknext;
4134 srv->tracknext = newsrv;
4135
4136 free(newsrv->trackit);
4137 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004138 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 newsrv = newsrv->next;
4140 }
4141
Willy Tarreauc1a21672009-08-16 22:37:44 +02004142 if (curproxy->cap & PR_CAP_FE) {
4143 if (curproxy->tcp_req.inspect_delay ||
4144 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4145 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4146
4147 if (curproxy->mode == PR_MODE_HTTP)
4148 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
4149
4150 /* both TCP and HTTP must check switching rules */
4151 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4152 }
4153
4154 if (curproxy->cap & PR_CAP_BE) {
4155 if (curproxy->mode == PR_MODE_HTTP)
4156 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
4157
4158 /* If the backend does requires RDP cookie persistence, we have to
4159 * enable the corresponding analyser.
4160 */
4161 if (curproxy->options2 & PR_O2_RDPC_PRST)
4162 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4163 }
4164
Willy Tarreaue6b98942007-10-29 01:09:36 +01004165 /* adjust this proxy's listeners */
4166 listener = curproxy->listen;
4167 while (listener) {
4168 if (curproxy->options & PR_O_TCP_NOLING)
4169 listener->options |= LI_O_NOLINGER;
4170 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004171 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004172 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004173 listener->accept = event_accept;
4174 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004175 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004176 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004177
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004178 /* smart accept mode is automatic in HTTP mode */
4179 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4180 (curproxy->mode == PR_MODE_HTTP &&
4181 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4182 listener->options |= LI_O_NOQUICKACK;
4183
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004184 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004185 listener = listener->next;
4186 }
4187
Willy Tarreaubaaee002006-06-26 02:48:02 +02004188 curproxy = curproxy->next;
4189 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004190
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004191 /*
4192 * Recount currently required checks.
4193 */
4194
4195 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4196 int optnum;
4197
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004198 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4199 if (curproxy->options & cfg_opts[optnum].val)
4200 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004201
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004202 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4203 if (curproxy->options2 & cfg_opts2[optnum].val)
4204 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004205 }
4206
Willy Tarreaubb925012009-07-23 13:36:36 +02004207 if (cfgerr > 0)
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 out:
4210 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211}
4212
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004213/*
4214 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4215 * parsing sessions.
4216 */
4217void cfg_register_keywords(struct cfg_kw_list *kwl)
4218{
4219 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4220}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004222/*
4223 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4224 */
4225void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4226{
4227 LIST_DEL(&kwl->list);
4228 LIST_INIT(&kwl->list);
4229}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230
4231/*
4232 * Local variables:
4233 * c-indent-level: 8
4234 * c-basic-offset: 8
4235 * End:
4236 */