blob: 3828812255e315aec7a5b1fdb8efe3c51ff38458 [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 Tarreau27a674e2009-08-17 07:23:33 +0200448 else if (!strcmp(args[0], "tune.bufsize")) {
449 if (*(args[1]) == 0) {
450 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
451 err_code |= ERR_ALERT | ERR_FATAL;
452 goto out;
453 }
454 global.tune.bufsize = atol(args[1]);
455 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
456 global.tune.maxrewrite = global.tune.bufsize / 2;
457 }
458 else if (!strcmp(args[0], "tune.maxrewrite")) {
459 if (*(args[1]) == 0) {
460 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
461 err_code |= ERR_ALERT | ERR_FATAL;
462 goto out;
463 }
464 global.tune.maxrewrite = atol(args[1]);
465 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
466 global.tune.maxrewrite = global.tune.bufsize / 2;
467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 else if (!strcmp(args[0], "uid")) {
469 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200470 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 err_code |= ERR_ALERT;
472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 }
474 if (*(args[1]) == 0) {
475 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200476 err_code |= ERR_ALERT | ERR_FATAL;
477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
479 global.uid = atol(args[1]);
480 }
481 else if (!strcmp(args[0], "gid")) {
482 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200483 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200484 err_code |= ERR_ALERT;
485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 }
487 if (*(args[1]) == 0) {
488 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT | ERR_FATAL;
490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491 }
492 global.gid = atol(args[1]);
493 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200494 /* user/group name handling */
495 else if (!strcmp(args[0], "user")) {
496 struct passwd *ha_user;
497 if (global.uid != 0) {
498 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT;
500 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200501 }
502 errno = 0;
503 ha_user = getpwnam(args[1]);
504 if (ha_user != NULL) {
505 global.uid = (int)ha_user->pw_uid;
506 }
507 else {
508 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 +0200509 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200510 }
511 }
512 else if (!strcmp(args[0], "group")) {
513 struct group *ha_group;
514 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200515 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT;
517 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200518 }
519 errno = 0;
520 ha_group = getgrnam(args[1]);
521 if (ha_group != NULL) {
522 global.gid = (int)ha_group->gr_gid;
523 }
524 else {
525 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 +0200526 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200527 }
528 }
529 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 else if (!strcmp(args[0], "nbproc")) {
531 if (global.nbproc != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 }
541 global.nbproc = atol(args[1]);
542 }
543 else if (!strcmp(args[0], "maxconn")) {
544 if (global.maxconn != 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 Tarreaubaaee002006-06-26 02:48:02 +0200548 }
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 Tarreaubaaee002006-06-26 02:48:02 +0200553 }
554 global.maxconn = atol(args[1]);
555#ifdef SYSTEM_MAXCONN
556 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
557 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);
558 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200559 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 }
561#endif /* SYSTEM_MAXCONN */
562 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100563 else if (!strcmp(args[0], "maxpipes")) {
564 if (global.maxpipes != 0) {
565 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200566 err_code |= ERR_ALERT;
567 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100568 }
569 if (*(args[1]) == 0) {
570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100573 }
574 global.maxpipes = atol(args[1]);
575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 else if (!strcmp(args[0], "ulimit-n")) {
577 if (global.rlimit_nofile != 0) {
578 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 err_code |= ERR_ALERT;
580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 }
582 if (*(args[1]) == 0) {
583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 }
587 global.rlimit_nofile = atol(args[1]);
588 }
589 else if (!strcmp(args[0], "chroot")) {
590 if (global.chroot != NULL) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200592 err_code |= ERR_ALERT;
593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 }
600 global.chroot = strdup(args[1]);
601 }
602 else if (!strcmp(args[0], "pidfile")) {
603 if (global.pidfile != NULL) {
604 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200605 err_code |= ERR_ALERT;
606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 }
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT | ERR_FATAL;
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 }
613 global.pidfile = strdup(args[1]);
614 }
615 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100616 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200617 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618
619 if (*(args[1]) == 0 || *(args[2]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624
625 facility = get_log_facility(args[2]);
626 if (facility < 0) {
627 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
629 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
631
632 level = 7; /* max syslog level = debug */
633 if (*(args[3])) {
634 level = get_log_level(args[3]);
635 if (level < 0) {
636 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 }
641
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200642 minlvl = 0; /* limit syslog level to this level (emerg) */
643 if (*(args[4])) {
644 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200646 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200649 }
650 }
651
Robert Tsai81ae1952007-12-05 10:47:29 +0100652 if (args[1][0] == '/') {
653 logsrv.u.addr.sa_family = AF_UNIX;
654 logsrv.u.un = *str2sun(args[1]);
655 } else {
656 logsrv.u.addr.sa_family = AF_INET;
657 logsrv.u.in = *str2sa(args[1]);
658 if (!logsrv.u.in.sin_port)
659 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661
662 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100663 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 global.logfac1 = facility;
665 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200666 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 }
668 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100669 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.logfac2 = facility;
671 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200672 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 }
674 else {
675 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200678 }
679 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
680 if (global.spread_checks != 0) {
681 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT;
683 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200684 }
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200689 }
690 global.spread_checks = atol(args[1]);
691 if (global.spread_checks < 0 || global.spread_checks > 50) {
692 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200697 struct cfg_kw_list *kwl;
698 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200699 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200700
701 list_for_each_entry(kwl, &cfg_keywords.list, list) {
702 for (index = 0; kwl->kw[index].kw != NULL; index++) {
703 if (kwl->kw[index].section != CFG_GLOBAL)
704 continue;
705 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
706 /* prepare error message just in case */
707 snprintf(trash, sizeof(trash),
708 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200709 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
710 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200711 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200713 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200714 else if (rc > 0) {
715 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200716 err_code |= ERR_WARN;
717 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200718 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200720 }
721 }
722 }
723
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 out:
728 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729}
730
731
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200732void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733{
734 memset(&defproxy, 0, sizeof(defproxy));
735 defproxy.mode = PR_MODE_TCP;
736 defproxy.state = PR_STNEW;
737 defproxy.maxconn = cfg_maxpconn;
738 defproxy.conn_retries = CONN_RETRIES;
739 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200740
741 LIST_INIT(&defproxy.pendconns);
742 LIST_INIT(&defproxy.acl);
743 LIST_INIT(&defproxy.block_cond);
744 LIST_INIT(&defproxy.mon_fail_cond);
745 LIST_INIT(&defproxy.switching_rules);
746
Willy Tarreau3a70f942008-02-15 11:15:34 +0100747 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200748}
749
750/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100751 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200752 * Returns the error code, 0 if OK, or any combination of :
753 * - ERR_ABORT: must abort ASAP
754 * - ERR_FATAL: we can continue parsing but not start the service
755 * - ERR_WARN: a warning has been emitted
756 * - ERR_ALERT: an alert has been emitted
757 * Only the two first ones can stop processing, the two others are just
758 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200760int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761{
762 static struct proxy *curproxy = NULL;
763 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200764 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100765 int rc;
766 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200767 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768
Willy Tarreau977b8e42006-12-29 14:19:17 +0100769 if (!strcmp(args[0], "listen"))
770 rc = PR_CAP_LISTEN;
771 else if (!strcmp(args[0], "frontend"))
772 rc = PR_CAP_FE | PR_CAP_RS;
773 else if (!strcmp(args[0], "backend"))
774 rc = PR_CAP_BE | PR_CAP_RS;
775 else if (!strcmp(args[0], "ruleset"))
776 rc = PR_CAP_RS;
777 else
778 rc = PR_CAP_NONE;
779
780 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 if (!*args[1]) {
782 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
783 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200785 err_code |= ERR_ALERT | ERR_ABORT;
786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200788
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100789 err = invalid_char(args[1]);
790 if (err) {
791 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
792 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100794 }
795
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200796 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
797 /*
798 * If there are two proxies with the same name only following
799 * combinations are allowed:
800 *
801 * listen backend frontend ruleset
802 * listen - - - -
803 * backend - - OK -
804 * frontend - OK - -
805 * ruleset - - - -
806 */
807
808 if (!strcmp(curproxy->id, args[1]) &&
809 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
810 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100811 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
812 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Willy Tarreau93893792009-07-23 13:19:11 +0200813 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200814 }
815 }
816
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
818 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200819 err_code |= ERR_ALERT | ERR_ABORT;
820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100822
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 curproxy->next = proxy;
824 proxy = curproxy;
825 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200826 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200827 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200828 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100829 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200830 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200831 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832
Willy Tarreauee991362007-05-14 14:37:50 +0200833 /* Timeouts are defined as -1, so we cannot use the zeroed area
834 * as a default value.
835 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100836 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200837
838 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100840 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841
842 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100843 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 curproxy->listen = str2listener(args[2], curproxy->listen);
Willy Tarreau93893792009-07-23 13:19:11 +0200845 if (!curproxy->listen) {
846 err_code |= ERR_FATAL;
847 goto out;
848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 global.maxsock++;
850 }
851
852 /* set default values */
853 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100855 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200856 curproxy->no_options = defproxy.no_options;
857 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100858 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100859 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200860 curproxy->except_net = defproxy.except_net;
861 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200862 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200863 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200865 if (defproxy.fwdfor_hdr_len) {
866 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
867 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
868 }
869
Willy Tarreau977b8e42006-12-29 14:19:17 +0100870 if (curproxy->cap & PR_CAP_FE) {
871 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100872 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +0200873 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100874
875 /* initialize error relocations */
876 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
877 if (defproxy.errmsg[rc].str)
878 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
879 }
880
881 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883
Willy Tarreau977b8e42006-12-29 14:19:17 +0100884 if (curproxy->cap & PR_CAP_BE) {
885 curproxy->fullconn = defproxy.fullconn;
886 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887
Willy Tarreau977b8e42006-12-29 14:19:17 +0100888 if (defproxy.check_req)
889 curproxy->check_req = strdup(defproxy.check_req);
890 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891
Willy Tarreau977b8e42006-12-29 14:19:17 +0100892 if (defproxy.cookie_name)
893 curproxy->cookie_name = strdup(defproxy.cookie_name);
894 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100895
Emeric Brun647caf12009-06-30 17:57:00 +0200896 if (defproxy.rdp_cookie_name)
897 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
898 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
899
Willy Tarreau01732802007-11-01 22:48:15 +0100900 if (defproxy.url_param_name)
901 curproxy->url_param_name = strdup(defproxy.url_param_name);
902 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100903
Benoitaffb4812009-03-25 13:02:10 +0100904 if (defproxy.hh_name)
905 curproxy->hh_name = strdup(defproxy.hh_name);
906 curproxy->hh_len = defproxy.hh_len;
907 curproxy->hh_match_domain = defproxy.hh_match_domain;
908
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100909 if (defproxy.iface_name)
910 curproxy->iface_name = strdup(defproxy.iface_name);
911 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913
Willy Tarreau3b6b1a92009-07-23 13:24:23 +0200914 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +0100915 if (defproxy.capture_name)
916 curproxy->capture_name = strdup(defproxy.capture_name);
917 curproxy->capture_namelen = defproxy.capture_namelen;
918 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920
Willy Tarreau977b8e42006-12-29 14:19:17 +0100921 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100922 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100923 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100924 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100925 curproxy->uri_auth = defproxy.uri_auth;
926 curproxy->mon_net = defproxy.mon_net;
927 curproxy->mon_mask = defproxy.mon_mask;
928 if (defproxy.monitor_uri)
929 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
930 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100931 if (defproxy.defbe.name)
932 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100933 }
934
935 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100936 curproxy->timeout.connect = defproxy.timeout.connect;
937 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100938 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100939 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100940 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +0200941 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100942 curproxy->source_addr = defproxy.source_addr;
943 }
944
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 curproxy->mode = defproxy.mode;
946 curproxy->logfac1 = defproxy.logfac1;
947 curproxy->logsrv1 = defproxy.logsrv1;
948 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200949 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 curproxy->logfac2 = defproxy.logfac2;
951 curproxy->logsrv2 = defproxy.logsrv2;
952 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200953 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100955 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
956 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200957
Willy Tarreau93893792009-07-23 13:19:11 +0200958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
960 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
961 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100962 /* FIXME-20070101: we should do this too at the end of the
963 * config parsing to free all default values.
964 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200965 free(defproxy.check_req);
966 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +0200967 free(defproxy.rdp_cookie_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200968 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +0100969 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +0200970 free(defproxy.capture_name);
971 free(defproxy.monitor_uri);
972 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100973 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200974 free(defproxy.fwdfor_hdr_name);
975 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100976
Willy Tarreaua534fea2008-08-03 12:19:50 +0200977 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
978 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100979
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 /* we cannot free uri_auth because it might already be used */
981 init_default_instance();
982 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100983 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +0200984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986 else if (curproxy == NULL) {
987 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991
Willy Tarreau977b8e42006-12-29 14:19:17 +0100992
993 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100995 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100996 int cur_arg;
997
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 if (curproxy == &defproxy) {
999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001003 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001004 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005
1006 if (strchr(args[1], ':') == NULL) {
1007 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001011 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001012
1013 last_listen = curproxy->listen;
1014 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreau93893792009-07-23 13:19:11 +02001015 if (!curproxy->listen) {
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001019
1020 cur_arg = 2;
1021 while (*(args[cur_arg])) {
1022 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1023#ifdef SO_BINDTODEVICE
1024 struct listener *l;
1025
1026 if (!*args[cur_arg + 1]) {
1027 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001031 }
1032
1033 for (l = curproxy->listen; l != last_listen; l = l->next)
1034 l->interface = strdup(args[cur_arg + 1]);
1035
1036 global.last_checks |= LSTCHK_NETADM;
1037
1038 cur_arg += 2;
1039 continue;
1040#else
1041 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1042 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
1044 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001045#endif
1046 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001047 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1048#ifdef TCP_MAXSEG
1049 struct listener *l;
1050 int mss;
1051
1052 if (!*args[cur_arg + 1]) {
1053 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1054 file, linenum, args[0]);
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 }
1058
1059 mss = str2uic(args[cur_arg + 1]);
1060 if (mss < 1 || mss > 65535) {
1061 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001065 }
1066
1067 for (l = curproxy->listen; l != last_listen; l = l->next)
1068 l->maxseg = mss;
1069
1070 cur_arg += 2;
1071 continue;
1072#else
1073 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1074 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001077#endif
1078 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001079 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001080#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001081 struct listener *l;
1082
1083 for (l = curproxy->listen; l != last_listen; l = l->next)
1084 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001085
1086 cur_arg ++;
1087 continue;
1088#else
1089 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1090 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001091 err_code |= ERR_ALERT | ERR_FATAL;
1092 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001093#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001094 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001095 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001096 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001097 err_code |= ERR_ALERT | ERR_FATAL;
1098 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 }
1103 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1104 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1105 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001110 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001111 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001112
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 /* flush useless bits */
1114 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001117 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001118 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001119 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001120
Willy Tarreau1c47f852006-07-09 08:22:27 +02001121 if (!*args[1]) {
1122 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001126 }
1127
Willy Tarreaua534fea2008-08-03 12:19:50 +02001128 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001129 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001130 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001131 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001132 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1133
Willy Tarreau93893792009-07-23 13:19:11 +02001134 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1137 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1138 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1139 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1140 else {
1141 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001146 else if (!strcmp(args[0], "id")) {
1147 struct proxy *target;
1148
1149 if (curproxy == &defproxy) {
1150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001154 }
1155
1156 if (!*args[1]) {
1157 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001161 }
1162
1163 curproxy->uuid = atol(args[1]);
1164
1165 if (curproxy->uuid < 1001) {
1166 Alert("parsing [%s:%d]: custom id has to be > 1000",
1167 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001168 err_code |= ERR_ALERT | ERR_FATAL;
1169 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001170 }
1171
1172 for (target = proxy; target; target = target->next)
1173 if (curproxy != target && curproxy->uuid == target->uuid) {
1174 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1175 file, linenum, curproxy->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001178 }
1179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1181 curproxy->state = PR_STSTOPPED;
1182 }
1183 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1184 curproxy->state = PR_STNEW;
1185 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001186 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1187 int cur_arg = 1;
1188 unsigned int set = 0;
1189
1190 while (*args[cur_arg]) {
1191 int u;
1192 if (strcmp(args[cur_arg], "all") == 0) {
1193 set = 0;
1194 break;
1195 }
1196 else if (strcmp(args[cur_arg], "odd") == 0) {
1197 set |= 0x55555555;
1198 }
1199 else if (strcmp(args[cur_arg], "even") == 0) {
1200 set |= 0xAAAAAAAA;
1201 }
1202 else {
1203 u = str2uic(args[cur_arg]);
1204 if (u < 1 || u > 32) {
1205 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001209 }
1210 if (u > global.nbproc) {
1211 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001213 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001214 }
1215 set |= 1 << (u - 1);
1216 }
1217 cur_arg++;
1218 }
1219 curproxy->bind_proc = set;
1220 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001221 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001222 if (curproxy == &defproxy) {
1223 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001226 }
1227
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001228 err = invalid_char(args[1]);
1229 if (err) {
1230 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1231 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001232 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001233 }
1234
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001235 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1236 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1237 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001240 }
1241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001242 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1243 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001244
Willy Tarreau977b8e42006-12-29 14:19:17 +01001245 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001246 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001247
Willy Tarreaubaaee002006-06-26 02:48:02 +02001248 if (*(args[1]) == 0) {
1249 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001254
1255 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001256 curproxy->cookie_name = strdup(args[1]);
1257 curproxy->cookie_len = strlen(curproxy->cookie_name);
1258
1259 cur_arg = 2;
1260 while (*(args[cur_arg])) {
1261 if (!strcmp(args[cur_arg], "rewrite")) {
1262 curproxy->options |= PR_O_COOK_RW;
1263 }
1264 else if (!strcmp(args[cur_arg], "indirect")) {
1265 curproxy->options |= PR_O_COOK_IND;
1266 }
1267 else if (!strcmp(args[cur_arg], "insert")) {
1268 curproxy->options |= PR_O_COOK_INS;
1269 }
1270 else if (!strcmp(args[cur_arg], "nocache")) {
1271 curproxy->options |= PR_O_COOK_NOC;
1272 }
1273 else if (!strcmp(args[cur_arg], "postonly")) {
1274 curproxy->options |= PR_O_COOK_POST;
1275 }
1276 else if (!strcmp(args[cur_arg], "prefix")) {
1277 curproxy->options |= PR_O_COOK_PFX;
1278 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001279 else if (!strcmp(args[cur_arg], "domain")) {
1280 if (!*args[cur_arg + 1]) {
1281 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1282 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001285 }
1286
1287 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1288 /* rfc2109, 4.3.2 Rejecting Cookies */
1289 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1290 " dots or does not start with a dot.\n",
1291 file, linenum, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001294 }
1295
1296 err = invalid_domainchar(args[cur_arg + 1]);
1297 if (err) {
1298 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1299 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001302 }
1303
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001304 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001305 cur_arg++;
1306 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001308 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001310 err_code |= ERR_ALERT | ERR_FATAL;
1311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 }
1313 cur_arg++;
1314 }
1315 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1316 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 }
1320
1321 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1322 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1323 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 }
1326 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001327 else if (!strcmp(args[0], "persist")) { /* persist */
1328 if (*(args[1]) == 0) {
1329 Alert("parsing [%s:%d] : missing persist method.\n",
1330 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001333 }
1334
1335 if (!strncmp(args[1], "rdp-cookie", 10)) {
1336 curproxy->options2 |= PR_O2_RDPC_PRST;
1337
1338 if (*(args[1] + 10 ) == '(') { /* cookie name */
1339 const char *beg, *end;
1340
1341 beg = args[1] + 11;
1342 end = strchr(beg, ')');
1343
1344 if (!end || end == beg) {
1345 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1346 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001349 }
1350
1351 free(curproxy->rdp_cookie_name);
1352 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1353 curproxy->rdp_cookie_len = end-beg;
1354 }
1355 else if (*(args[1] + 10 ) == '\0') { /* default cookie name 'msts' */
1356 free(curproxy->rdp_cookie_name);
1357 curproxy->rdp_cookie_name = strdup("msts");
1358 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1359 }
1360 else { /* syntax */
1361 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1362 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001365 }
1366 }
1367 else {
1368 Alert("parsing [%s:%d] : unknown persist method.\n",
1369 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001372 }
1373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375
Willy Tarreau977b8e42006-12-29 14:19:17 +01001376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001378
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 if (*(args[5]) == 0) {
1380 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
1385 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001386 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 curproxy->appsession_name = strdup(args[1]);
1388 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1389 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001390 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1391 if (err) {
1392 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1393 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001396 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001397 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001398
Willy Tarreau51041c72007-09-09 21:56:53 +02001399 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_ABORT;
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 }
1404 } /* Url App Session */
1405 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001406 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001407 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001408
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 if (*(args[4]) == 0) {
1411 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1412 file, linenum, args[0]);
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 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001416 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 curproxy->capture_name = strdup(args[2]);
1418 curproxy->capture_namelen = strlen(curproxy->capture_name);
1419 curproxy->capture_len = atol(args[4]);
1420 if (curproxy->capture_len >= CAPTURE_LEN) {
1421 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1422 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001423 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424 curproxy->capture_len = CAPTURE_LEN - 1;
1425 }
1426 curproxy->to_log |= LW_COOKIE;
1427 }
1428 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1429 struct cap_hdr *hdr;
1430
1431 if (curproxy == &defproxy) {
1432 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 +02001433 err_code |= ERR_ALERT | ERR_FATAL;
1434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 }
1436
1437 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1438 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1439 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 }
1443
1444 hdr = calloc(sizeof(struct cap_hdr), 1);
1445 hdr->next = curproxy->req_cap;
1446 hdr->name = strdup(args[3]);
1447 hdr->namelen = strlen(args[3]);
1448 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001449 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 hdr->index = curproxy->nb_req_cap++;
1451 curproxy->req_cap = hdr;
1452 curproxy->to_log |= LW_REQHDR;
1453 }
1454 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1455 struct cap_hdr *hdr;
1456
1457 if (curproxy == &defproxy) {
1458 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 +02001459 err_code |= ERR_ALERT | ERR_FATAL;
1460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462
1463 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1464 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1465 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
1469 hdr = calloc(sizeof(struct cap_hdr), 1);
1470 hdr->next = curproxy->rsp_cap;
1471 hdr->name = strdup(args[3]);
1472 hdr->namelen = strlen(args[3]);
1473 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001474 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 hdr->index = curproxy->nb_rsp_cap++;
1476 curproxy->rsp_cap = hdr;
1477 curproxy->to_log |= LW_RSPHDR;
1478 }
1479 else {
1480 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484 }
1485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001487 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 if (*(args[1]) == 0) {
1491 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1492 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001493 err_code |= ERR_ALERT | ERR_FATAL;
1494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 }
1496 curproxy->conn_retries = atol(args[1]);
1497 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001498 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1499 int pol = ACL_COND_NONE;
1500 struct acl_cond *cond;
1501
Willy Tarreaub099aca2008-10-12 17:26:37 +02001502 if (curproxy == &defproxy) {
1503 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001506 }
1507
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001508 if (!strcmp(args[1], "if"))
1509 pol = ACL_COND_IF;
1510 else if (!strcmp(args[1], "unless"))
1511 pol = ACL_COND_UNLESS;
1512
1513 if (pol == ACL_COND_NONE) {
1514 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1515 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001518 }
1519
1520 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1521 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001525 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001526 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001527 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001528 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001529 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001530 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001531 else if (!strcmp(args[0], "redirect")) {
1532 int pol = ACL_COND_NONE;
1533 struct acl_cond *cond;
1534 struct redirect_rule *rule;
1535 int cur_arg;
1536 int type = REDIRECT_TYPE_NONE;
1537 int code = 302;
1538 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001539 char *cookie = NULL;
1540 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001541 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001542
1543 cur_arg = 1;
1544 while (*(args[cur_arg])) {
1545 if (!strcmp(args[cur_arg], "location")) {
1546 if (!*args[cur_arg + 1]) {
1547 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1548 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001551 }
1552
1553 type = REDIRECT_TYPE_LOCATION;
1554 cur_arg++;
1555 destination = args[cur_arg];
1556 }
1557 else if (!strcmp(args[cur_arg], "prefix")) {
1558 if (!*args[cur_arg + 1]) {
1559 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1560 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001563 }
1564
1565 type = REDIRECT_TYPE_PREFIX;
1566 cur_arg++;
1567 destination = args[cur_arg];
1568 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001569 else if (!strcmp(args[cur_arg], "set-cookie")) {
1570 if (!*args[cur_arg + 1]) {
1571 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1572 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001575 }
1576
1577 cur_arg++;
1578 cookie = args[cur_arg];
1579 cookie_set = 1;
1580 }
1581 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1582 if (!*args[cur_arg + 1]) {
1583 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001587 }
1588
1589 cur_arg++;
1590 cookie = args[cur_arg];
1591 cookie_set = 0;
1592 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001593 else if (!strcmp(args[cur_arg],"code")) {
1594 if (!*args[cur_arg + 1]) {
1595 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001599 }
1600 cur_arg++;
1601 code = atol(args[cur_arg]);
1602 if (code < 301 || code > 303) {
1603 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1604 file, linenum, args[0], code);
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 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001609 else if (!strcmp(args[cur_arg],"drop-query")) {
1610 flags |= REDIRECT_FLAG_DROP_QS;
1611 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001612 else if (!strcmp(args[cur_arg], "if")) {
1613 pol = ACL_COND_IF;
1614 cur_arg++;
1615 break;
1616 }
1617 else if (!strcmp(args[cur_arg], "unless")) {
1618 pol = ACL_COND_UNLESS;
1619 cur_arg++;
1620 break;
1621 }
1622 else {
1623 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1624 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001627 }
1628 cur_arg++;
1629 }
1630
1631 if (type == REDIRECT_TYPE_NONE) {
1632 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1633 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001636 }
1637
1638 if (pol == ACL_COND_NONE) {
1639 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1640 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001643 }
1644
1645 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001646 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001650 }
1651
Willy Tarreaua9802632008-07-25 19:13:19 +02001652 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001653 curproxy->acl_requires |= cond->requires;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001654 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1655 rule->cond = cond;
1656 rule->rdr_str = strdup(destination);
1657 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001658 if (cookie) {
1659 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1660 * a clear consists in appending "; Max-Age=0" at the end.
1661 */
1662 rule->cookie_len = strlen(cookie);
1663 if (cookie_set)
1664 rule->cookie_str = strdup(cookie);
1665 else {
1666 rule->cookie_str = malloc(rule->cookie_len + 12);
1667 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1668 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1669 rule->cookie_len += 11;
1670 }
1671 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001672 rule->type = type;
1673 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001674 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001675 LIST_INIT(&rule->list);
1676 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001677 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001678 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001679 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001680 int pol = ACL_COND_NONE;
1681 struct acl_cond *cond;
1682 struct switching_rule *rule;
1683
Willy Tarreaub099aca2008-10-12 17:26:37 +02001684 if (curproxy == &defproxy) {
1685 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001688 }
1689
Willy Tarreau55ea7572007-06-17 19:56:27 +02001690 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001692
1693 if (*(args[1]) == 0) {
1694 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001697 }
1698
1699 if (!strcmp(args[2], "if"))
1700 pol = ACL_COND_IF;
1701 else if (!strcmp(args[2], "unless"))
1702 pol = ACL_COND_UNLESS;
1703
1704 if (pol == ACL_COND_NONE) {
1705 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1706 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001709 }
1710
1711 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001712 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001713 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001716 }
1717
Willy Tarreaua9802632008-07-25 19:13:19 +02001718 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001719 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02001720 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001721 struct acl *acl;
1722 const char *name;
1723
1724 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1725 name = acl ? acl->name : "(unknown)";
1726 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1727 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02001729 }
1730
Willy Tarreau55ea7572007-06-17 19:56:27 +02001731 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1732 rule->cond = cond;
1733 rule->be.name = strdup(args[1]);
1734 LIST_INIT(&rule->list);
1735 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001740
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1742 curproxy->uri_auth = NULL; /* we must detach from the default config */
1743
1744 if (*(args[1]) == 0) {
Willy Tarreau1d45b7c2009-08-16 10:29:18 +02001745 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 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
1747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 } else if (!strcmp(args[1], "uri")) {
1749 if (*(args[2]) == 0) {
1750 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1754 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001755 err_code |= ERR_ALERT | ERR_ABORT;
1756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758 } else if (!strcmp(args[1], "realm")) {
1759 if (*(args[2]) == 0) {
1760 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
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 Tarreaubaaee002006-06-26 02:48:02 +02001767 }
Willy Tarreau1d45b7c2009-08-16 10:29:18 +02001768 } else if (!strcmp(args[1], "node-name")) {
1769 if (!stats_set_node_name(&curproxy->uri_auth, *(args[2]) ? args[2] : hostname)) {
1770 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1771 err_code |= ERR_ALERT | ERR_ABORT;
1772 goto out;
1773 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001774 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001775 unsigned interval;
1776
1777 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1778 if (err) {
1779 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1780 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02001783 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02001787 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 } else if (!strcmp(args[1], "auth")) {
1789 if (*(args[2]) == 0) {
1790 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1794 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001795 err_code |= ERR_ALERT | ERR_ABORT;
1796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
1798 } else if (!strcmp(args[1], "scope")) {
1799 if (*(args[2]) == 0) {
1800 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1804 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_ALERT | ERR_ABORT;
1806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 }
1808 } else if (!strcmp(args[1], "enable")) {
1809 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1810 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_ALERT | ERR_ABORT;
1812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001814 } else if (!strcmp(args[1], "hide-version")) {
1815 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1816 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_ALERT | ERR_ABORT;
1818 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001821 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 }
1826 }
1827 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001828 int optnum;
1829
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001830 if (*(args[1]) == '\0') {
1831 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001836
1837 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1838 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001839 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
1840 err_code |= ERR_WARN;
1841 goto out;
1842 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001843
Willy Tarreau3842f002009-06-14 11:39:52 +02001844 curproxy->no_options &= ~cfg_opts[optnum].val;
1845 curproxy->options &= ~cfg_opts[optnum].val;
1846
1847 switch (kwm) {
1848 case KWM_STD:
1849 curproxy->options |= cfg_opts[optnum].val;
1850 break;
1851 case KWM_NO:
1852 curproxy->no_options |= cfg_opts[optnum].val;
1853 break;
1854 case KWM_DEF: /* already cleared */
1855 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001856 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001857
Willy Tarreau93893792009-07-23 13:19:11 +02001858 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001859 }
1860 }
1861
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001862 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1863 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001864 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
1865 err_code |= ERR_WARN;
1866 goto out;
1867 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001868
Willy Tarreau3842f002009-06-14 11:39:52 +02001869 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
1870 curproxy->options2 &= ~cfg_opts2[optnum].val;
1871
1872 switch (kwm) {
1873 case KWM_STD:
1874 curproxy->options2 |= cfg_opts2[optnum].val;
1875 break;
1876 case KWM_NO:
1877 curproxy->no_options2 |= cfg_opts2[optnum].val;
1878 break;
1879 case KWM_DEF: /* already cleared */
1880 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001881 }
Willy Tarreau93893792009-07-23 13:19:11 +02001882 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001883 }
1884 }
1885
Willy Tarreau3842f002009-06-14 11:39:52 +02001886 if (kwm != KWM_STD) {
1887 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001888 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001891 }
1892
Emeric Brun3a058f32009-06-30 18:26:00 +02001893 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02001895 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02001897 if (*(args[2]) != '\0') {
1898 if (!strcmp(args[2], "clf")) {
1899 curproxy->options2 |= PR_O2_CLFLOG;
1900 } else {
1901 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02001904 }
1905 }
1906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 else if (!strcmp(args[1], "tcplog"))
1908 /* generate a detailed TCP log */
1909 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 else if (!strcmp(args[1], "tcpka")) {
1911 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001912 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001914
1915 if (curproxy->cap & PR_CAP_FE)
1916 curproxy->options |= PR_O_TCP_CLI_KA;
1917 if (curproxy->cap & PR_CAP_BE)
1918 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 }
1920 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001921 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001922 err_code |= ERR_WARN;
1923
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001925 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001926 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001927 curproxy->options &= ~PR_O_SMTP_CHK;
1928 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 if (!*args[2]) { /* no argument */
1930 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1931 curproxy->check_len = strlen(DEF_CHECK_REQ);
1932 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001933 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 curproxy->check_req = (char *)malloc(reqlen);
1935 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1936 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1937 } else { /* more arguments : METHOD URI [HTTP_VER] */
1938 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1939 if (*args[4])
1940 reqlen += strlen(args[4]);
1941 else
1942 reqlen += strlen("HTTP/1.0");
1943
1944 curproxy->check_req = (char *)malloc(reqlen);
1945 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1946 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1947 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001948 }
1949 else if (!strcmp(args[1], "ssl-hello-chk")) {
1950 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001951 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01001953
Willy Tarreaua534fea2008-08-03 12:19:50 +02001954 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001955 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001956 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001957 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 }
Willy Tarreau23677902007-05-08 23:50:35 +02001959 else if (!strcmp(args[1], "smtpchk")) {
1960 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001961 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001962 curproxy->options &= ~PR_O_HTTP_CHK;
1963 curproxy->options &= ~PR_O_SSL3_CHK;
1964 curproxy->options |= PR_O_SMTP_CHK;
1965
1966 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1967 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1968 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1969 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1970 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1971 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1972 curproxy->check_req = (char *)malloc(reqlen);
1973 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1974 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1975 } else {
1976 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1977 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1978 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1979 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1980 }
1981 }
1982 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001983 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001984 int cur_arg;
1985
1986 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1987 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001988 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001989
1990 curproxy->options |= PR_O_FWDFOR;
1991
1992 free(curproxy->fwdfor_hdr_name);
1993 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1994 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1995
1996 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1997 cur_arg = 2;
1998 while (*(args[cur_arg])) {
1999 if (!strcmp(args[cur_arg], "except")) {
2000 /* suboption except - needs additional argument for it */
2001 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2002 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2003 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002004 err_code |= ERR_ALERT | ERR_FATAL;
2005 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002006 }
2007 /* flush useless bits */
2008 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002009 cur_arg += 2;
2010 } else if (!strcmp(args[cur_arg], "header")) {
2011 /* suboption header - needs additional argument for it */
2012 if (*(args[cur_arg+1]) == 0) {
2013 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2014 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002017 }
2018 free(curproxy->fwdfor_hdr_name);
2019 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2020 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2021 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002022 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002023 /* unknown suboption - catchall */
2024 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2025 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002028 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002029 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002030 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002031 else if (!strcmp(args[1], "originalto")) {
2032 int cur_arg;
2033
2034 /* insert x-original-to field, but not for the IP address listed as an except.
2035 * set default options (ie: bitfield, header name, etc)
2036 */
2037
2038 curproxy->options |= PR_O_ORGTO;
2039
2040 free(curproxy->orgto_hdr_name);
2041 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2042 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2043
2044 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2045 cur_arg = 2;
2046 while (*(args[cur_arg])) {
2047 if (!strcmp(args[cur_arg], "except")) {
2048 /* suboption except - needs additional argument for it */
2049 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2050 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2051 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002054 }
2055 /* flush useless bits */
2056 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2057 cur_arg += 2;
2058 } else if (!strcmp(args[cur_arg], "header")) {
2059 /* suboption header - needs additional argument for it */
2060 if (*(args[cur_arg+1]) == 0) {
2061 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2062 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002065 }
2066 free(curproxy->orgto_hdr_name);
2067 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2068 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2069 cur_arg += 2;
2070 } else {
2071 /* unknown suboption - catchall */
2072 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2073 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002076 }
2077 } /* end while loop */
2078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 else {
2080 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 }
Willy Tarreau93893792009-07-23 13:19:11 +02002084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002086 else if (!strcmp(args[0], "default_backend")) {
2087 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002089
2090 if (*(args[1]) == 0) {
2091 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002094 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002095 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002096 curproxy->defbe.name = strdup(args[1]);
2097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002102 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 /* enable reconnections to dispatch */
2106 curproxy->options |= PR_O_REDISP;
2107 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002108 else if (!strcmp(args[0], "http-check")) {
2109 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002111
2112 if (strcmp(args[1], "disable-on-404") == 0) {
2113 /* enable a graceful server shutdown on an HTTP 404 response */
2114 curproxy->options |= PR_O_DISABLE404;
2115 }
2116 else {
2117 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002120 }
2121 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002122 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002123 if (curproxy == &defproxy) {
2124 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002127 }
2128
Willy Tarreaub80c2302007-11-30 20:51:32 +01002129 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002131
2132 if (strcmp(args[1], "fail") == 0) {
2133 /* add a condition to fail monitor requests */
2134 int pol = ACL_COND_NONE;
2135 struct acl_cond *cond;
2136
2137 if (!strcmp(args[2], "if"))
2138 pol = ACL_COND_IF;
2139 else if (!strcmp(args[2], "unless"))
2140 pol = ACL_COND_UNLESS;
2141
2142 if (pol == ACL_COND_NONE) {
2143 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002147 }
2148
2149 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2150 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2151 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002154 }
Willy Tarreaua9802632008-07-25 19:13:19 +02002155 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002156 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002157 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2158 }
2159 else {
2160 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002163 }
2164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165#ifdef TPROXY
2166 else if (!strcmp(args[0], "transparent")) {
2167 /* enable transparent proxy connections */
2168 curproxy->options |= PR_O_TRANSP;
2169 }
2170#endif
2171 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 if (*(args[1]) == 0) {
2176 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 }
2180 curproxy->maxconn = atol(args[1]);
2181 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002182 else if (!strcmp(args[0], "backlog")) { /* backlog */
2183 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002185
2186 if (*(args[1]) == 0) {
2187 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002190 }
2191 curproxy->backlog = atol(args[1]);
2192 }
Willy Tarreau86034312006-12-29 00:10:33 +01002193 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002194 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002196
Willy Tarreau86034312006-12-29 00:10:33 +01002197 if (*(args[1]) == 0) {
2198 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002201 }
2202 curproxy->fullconn = atol(args[1]);
2203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2205 if (*(args[1]) == 0) {
2206 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002210 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2211 if (err) {
2212 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2213 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002216 }
2217 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
2219 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2220 if (curproxy == &defproxy) {
2221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 if (strchr(args[1], ':') == NULL) {
2229 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
2233 curproxy->dispatch_addr = *str2sa(args[1]);
2234 }
2235 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002236 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002238
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002239 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002240 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2241 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 else if (!strcmp(args[0], "server")) { /* server address */
2247 int cur_arg;
2248 char *rport;
2249 char *raddr;
2250 short realport;
2251 int do_check;
2252
2253 if (curproxy == &defproxy) {
2254 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260
2261 if (!*args[2]) {
2262 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002267
2268 err = invalid_char(args[1]);
2269 if (err) {
2270 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2271 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002274 }
2275
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_ABORT;
2279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
2281
2282 /* the servers are linked backwards first */
2283 newsrv->next = curproxy->srv;
2284 curproxy->srv = newsrv;
2285 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01002286 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287
2288 LIST_INIT(&newsrv->pendconns);
2289 do_check = 0;
2290 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002291 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 newsrv->id = strdup(args[1]);
2293
2294 /* several ways to check the port component :
2295 * - IP => port=+0, relative
2296 * - IP: => port=+0, relative
2297 * - IP:N => port=N, absolute
2298 * - IP:+N => port=+N, relative
2299 * - IP:-N => port=-N, relative
2300 */
2301 raddr = strdup(args[2]);
2302 rport = strchr(raddr, ':');
2303 if (rport) {
2304 *rport++ = 0;
2305 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02002306 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02002307 newsrv->state |= SRV_MAPPORTS;
2308 } else {
2309 realport = 0;
2310 newsrv->state |= SRV_MAPPORTS;
2311 }
2312
2313 newsrv->addr = *str2sa(raddr);
2314 newsrv->addr.sin_port = htons(realport);
2315 free(raddr);
2316
2317 newsrv->curfd = -1; /* no health-check in progress */
2318 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002319 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
2320 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 newsrv->rise = DEF_RISETIME;
2322 newsrv->fall = DEF_FALLTIME;
2323 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02002324 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002325 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002326 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 cur_arg = 3;
2329 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002330 if (!strcmp(args[cur_arg], "id")) {
2331 struct server *target;
2332
2333 if (!*args[cur_arg + 1]) {
2334 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2335 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002338 }
2339
2340 newsrv->puid = atol(args[cur_arg + 1]);
2341
2342 if (newsrv->puid< 1001) {
2343 Alert("parsing [%s:%d]: custom id has to be > 1000",
2344 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002347 }
2348
2349 for (target = proxy->srv; target; target = target->next)
2350 if (newsrv != target && newsrv->puid == target->puid) {
2351 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2352 file, linenum, newsrv->id, target->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002355 }
2356 cur_arg += 2;
2357 }
2358 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 newsrv->cookie = strdup(args[cur_arg + 1]);
2360 newsrv->cklen = strlen(args[cur_arg + 1]);
2361 cur_arg += 2;
2362 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002363 else if (!strcmp(args[cur_arg], "redir")) {
2364 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2365 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2366 cur_arg += 2;
2367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 else if (!strcmp(args[cur_arg], "rise")) {
2369 newsrv->rise = atol(args[cur_arg + 1]);
2370 newsrv->health = newsrv->rise;
2371 cur_arg += 2;
2372 }
2373 else if (!strcmp(args[cur_arg], "fall")) {
2374 newsrv->fall = atol(args[cur_arg + 1]);
2375 cur_arg += 2;
2376 }
2377 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002378 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2379 if (err) {
2380 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2381 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002384 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002385 if (val <= 0) {
2386 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2387 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002390 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002391 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 cur_arg += 2;
2393 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002394 else if (!strcmp(args[cur_arg], "fastinter")) {
2395 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2396 if (err) {
2397 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2398 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002401 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002402 if (val <= 0) {
2403 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2404 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002407 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002408 newsrv->fastinter = val;
2409 cur_arg += 2;
2410 }
2411 else if (!strcmp(args[cur_arg], "downinter")) {
2412 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2413 if (err) {
2414 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2415 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002418 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002419 if (val <= 0) {
2420 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2421 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002424 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002425 newsrv->downinter = val;
2426 cur_arg += 2;
2427 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002428 else if (!strcmp(args[cur_arg], "addr")) {
2429 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002430 cur_arg += 2;
2431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 else if (!strcmp(args[cur_arg], "port")) {
2433 newsrv->check_port = atol(args[cur_arg + 1]);
2434 cur_arg += 2;
2435 }
2436 else if (!strcmp(args[cur_arg], "backup")) {
2437 newsrv->state |= SRV_BACKUP;
2438 cur_arg ++;
2439 }
2440 else if (!strcmp(args[cur_arg], "weight")) {
2441 int w;
2442 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02002443 if (w < 0 || w > 256) {
2444 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002449 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 cur_arg += 2;
2451 }
2452 else if (!strcmp(args[cur_arg], "minconn")) {
2453 newsrv->minconn = atol(args[cur_arg + 1]);
2454 cur_arg += 2;
2455 }
2456 else if (!strcmp(args[cur_arg], "maxconn")) {
2457 newsrv->maxconn = atol(args[cur_arg + 1]);
2458 cur_arg += 2;
2459 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002460 else if (!strcmp(args[cur_arg], "maxqueue")) {
2461 newsrv->maxqueue = atol(args[cur_arg + 1]);
2462 cur_arg += 2;
2463 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002464 else if (!strcmp(args[cur_arg], "slowstart")) {
2465 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002466 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002467 if (err) {
2468 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2469 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002472 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002473 if (val <= 0) {
2474 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2475 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01002478 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002479 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002480 cur_arg += 2;
2481 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002482 else if (!strcmp(args[cur_arg], "track")) {
2483
2484 if (!*args[cur_arg + 1]) {
2485 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2486 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002489 }
2490
2491 newsrv->trackit = strdup(args[cur_arg + 1]);
2492
2493 cur_arg += 2;
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 else if (!strcmp(args[cur_arg], "check")) {
2496 global.maxsock++;
2497 do_check = 1;
2498 cur_arg += 1;
2499 }
2500 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002501 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002503#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002504 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002505 file, linenum, "source", "usesrc");
2506#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002507 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002509#endif
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002514 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
2515
2516 if (port_low != port_high) {
2517 int i;
2518 if (port_low <= 0 || port_low > 65535 ||
2519 port_high <= 0 || port_high > 65535 ||
2520 port_low > port_high) {
2521 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
2522 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02002525 }
2526 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
2527 for (i = 0; i < newsrv->sport_range->size; i++)
2528 newsrv->sport_range->ports[i] = port_low + i;
2529 }
2530
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002532 while (*(args[cur_arg])) {
2533 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002534#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2535#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002536 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2537 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2538 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002541 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002542#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002543 if (!*args[cur_arg + 1]) {
2544 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2545 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 }
2549 if (!strcmp(args[cur_arg + 1], "client")) {
2550 newsrv->state |= SRV_TPROXY_CLI;
2551 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2552 newsrv->state |= SRV_TPROXY_CIP;
2553 } else {
2554 newsrv->state |= SRV_TPROXY_ADDR;
2555 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2556 }
2557 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002558#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002559 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002560#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002561 cur_arg += 2;
2562 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002563#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002564 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002565 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002568#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2569 } /* "usesrc" */
2570
2571 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2572#ifdef SO_BINDTODEVICE
2573 if (!*args[cur_arg + 1]) {
2574 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002578 }
2579 if (newsrv->iface_name)
2580 free(newsrv->iface_name);
2581
2582 newsrv->iface_name = strdup(args[cur_arg + 1]);
2583 newsrv->iface_len = strlen(newsrv->iface_name);
2584 global.last_checks |= LSTCHK_NETADM;
2585#else
2586 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2587 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01002590#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002591 cur_arg += 2;
2592 continue;
2593 }
2594 /* this keyword in not an option of "source" */
2595 break;
2596 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002598 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2599 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2600 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 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 +02002606 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
2610 }
2611
2612 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002613 if (newsrv->trackit) {
2614 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2615 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002618 }
2619
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002620 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2621 newsrv->check_port = newsrv->check_addr.sin_port;
2622
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2624 newsrv->check_port = realport; /* by default */
2625 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002626 /* not yet valid, because no port was set on
2627 * the server either. We'll check if we have
2628 * a known port on the first listener.
2629 */
2630 struct listener *l;
2631 l = curproxy->listen;
2632 if (l) {
2633 int port;
2634 port = (l->addr.ss_family == AF_INET6)
2635 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2636 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2637 newsrv->check_port = port;
2638 }
2639 }
2640 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2642 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
2646 newsrv->state |= SRV_CHECKED;
2647 }
2648
2649 if (newsrv->state & SRV_BACKUP)
2650 curproxy->srv_bck++;
2651 else
2652 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002653
2654 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 }
2656 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002657 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 int facility;
2659
2660 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2661 curproxy->logfac1 = global.logfac1;
2662 curproxy->logsrv1 = global.logsrv1;
2663 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002664 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 curproxy->logfac2 = global.logfac2;
2666 curproxy->logsrv2 = global.logsrv2;
2667 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002668 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002671 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672
2673 facility = get_log_facility(args[2]);
2674 if (facility < 0) {
2675 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2676 exit(1);
2677 }
2678
2679 level = 7; /* max syslog level = debug */
2680 if (*(args[3])) {
2681 level = get_log_level(args[3]);
2682 if (level < 0) {
2683 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2684 exit(1);
2685 }
2686 }
2687
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002688 minlvl = 0; /* limit syslog level to this level (emerg) */
2689 if (*(args[4])) {
2690 minlvl = get_log_level(args[4]);
2691 if (level < 0) {
2692 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
2693 exit(1);
2694 }
2695 }
2696
Robert Tsai81ae1952007-12-05 10:47:29 +01002697 if (args[1][0] == '/') {
2698 logsrv.u.addr.sa_family = AF_UNIX;
2699 logsrv.u.un = *str2sun(args[1]);
2700 } else {
2701 logsrv.u.addr.sa_family = AF_INET;
2702 logsrv.u.in = *str2sa(args[1]);
2703 if (!logsrv.u.in.sin_port) {
2704 logsrv.u.in.sin_port =
2705 htons(SYSLOG_PORT);
2706 }
2707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708
2709 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002710 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002711 curproxy->logfac1 = facility;
2712 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002713 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 }
2715 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002716 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 curproxy->logfac2 = facility;
2718 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02002719 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 }
2721 else {
2722 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
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 }
2726 }
2727 else {
2728 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2729 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 }
2733 }
2734 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002735 int cur_arg;
2736
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002739
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002741 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2742 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002746
2747 /* we must first clear any optional default setting */
2748 curproxy->options &= ~PR_O_TPXY_MASK;
2749 free(curproxy->iface_name);
2750 curproxy->iface_name = NULL;
2751 curproxy->iface_len = 0;
2752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 curproxy->source_addr = *str2sa(args[1]);
2754 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002755
2756 cur_arg = 2;
2757 while (*(args[cur_arg])) {
2758 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002759#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2760#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002761 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2762 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2763 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002766 }
2767#endif
2768 if (!*args[cur_arg + 1]) {
2769 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2770 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002773 }
2774
2775 if (!strcmp(args[cur_arg + 1], "client")) {
2776 curproxy->options |= PR_O_TPXY_CLI;
2777 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2778 curproxy->options |= PR_O_TPXY_CIP;
2779 } else {
2780 curproxy->options |= PR_O_TPXY_ADDR;
2781 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2782 }
2783 global.last_checks |= LSTCHK_NETADM;
2784#if !defined(CONFIG_HAP_LINUX_TPROXY)
2785 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002786#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002787#else /* no TPROXY support */
2788 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002789 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002792#endif
2793 cur_arg += 2;
2794 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002795 }
2796
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002797 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2798#ifdef SO_BINDTODEVICE
2799 if (!*args[cur_arg + 1]) {
2800 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2801 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002804 }
2805 if (curproxy->iface_name)
2806 free(curproxy->iface_name);
2807
2808 curproxy->iface_name = strdup(args[cur_arg + 1]);
2809 curproxy->iface_len = strlen(curproxy->iface_name);
2810 global.last_checks |= LSTCHK_NETADM;
2811#else
2812 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2813 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002816#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002817 cur_arg += 2;
2818 continue;
2819 }
2820 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2821 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002826 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2827 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2828 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2833 regex_t *preg;
2834 if (curproxy == &defproxy) {
2835 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002838 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002839 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002841
Willy Tarreaubaaee002006-06-26 02:48:02 +02002842 if (*(args[1]) == 0 || *(args[2]) == 0) {
2843 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 }
2848
2849 preg = calloc(1, sizeof(regex_t));
2850 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2851 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 }
2855
2856 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2857 if (err) {
2858 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2859 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002862 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2865 regex_t *preg;
2866 if (curproxy == &defproxy) {
2867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002871 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002873
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 if (*(args[1]) == 0) {
2875 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 }
2879
2880 preg = calloc(1, sizeof(regex_t));
2881 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2882 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
2886
2887 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002888 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
2890 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2891 regex_t *preg;
2892 if (curproxy == &defproxy) {
2893 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002899
Willy Tarreaubaaee002006-06-26 02:48:02 +02002900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 }
2905
2906 preg = calloc(1, sizeof(regex_t));
2907 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2908 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 }
2912
2913 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002914 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 }
2916 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2917 regex_t *preg;
2918 if (curproxy == &defproxy) {
2919 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002923 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002925
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926 if (*(args[1]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002930 }
2931
2932 preg = calloc(1, sizeof(regex_t));
2933 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2934 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002937 }
2938
2939 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002940 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002941 }
2942 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2943 regex_t *preg;
2944 if (curproxy == &defproxy) {
2945 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002948 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002949 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002950 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002951
Willy Tarreaubaaee002006-06-26 02:48:02 +02002952 if (*(args[1]) == 0) {
2953 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 }
2957
2958 preg = calloc(1, sizeof(regex_t));
2959 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2960 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963 }
2964
2965 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002966 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002968 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2969 regex_t *preg;
2970 if (curproxy == &defproxy) {
2971 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002975 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002977
Willy Tarreaub8750a82006-09-03 09:56:00 +02002978 if (*(args[1]) == 0) {
2979 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002982 }
2983
2984 preg = calloc(1, sizeof(regex_t));
2985 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2986 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02002989 }
2990
2991 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002992 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002993 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002994 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2995 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002996 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002997 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003000 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003003
Willy Tarreau977b8e42006-12-29 14:19:17 +01003004 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003005 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003009 }
3010
3011 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003012 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003013 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
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 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003019 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003020 }
3021 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3022 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003023 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003027 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003028 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003030
Willy Tarreau977b8e42006-12-29 14:19:17 +01003031 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003032 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003036 }
3037
3038 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003039 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003040 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003043 }
3044
3045 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003046 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3049 regex_t *preg;
3050 if (curproxy == &defproxy) {
3051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 if (*(args[1]) == 0 || *(args[2]) == 0) {
3059 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064
3065 preg = calloc(1, sizeof(regex_t));
3066 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3067 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
3071
3072 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3073 if (err) {
3074 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3075 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003079 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
3081 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3082 regex_t *preg;
3083 if (curproxy == &defproxy) {
3084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003088 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003090
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 if (*(args[1]) == 0) {
3092 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 }
3096
3097 preg = calloc(1, sizeof(regex_t));
3098 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3099 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
3103
3104 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003105 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 }
3107 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3108 regex_t *preg;
3109 if (curproxy == &defproxy) {
3110 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003114 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003116
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 if (*(args[1]) == 0) {
3118 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 }
3122
3123 preg = calloc(1, sizeof(regex_t));
3124 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3125 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 }
3129
3130 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003131 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
3133 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3134 regex_t *preg;
3135 if (curproxy == &defproxy) {
3136 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003140 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003142
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 if (*(args[1]) == 0) {
3144 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 preg = calloc(1, sizeof(regex_t));
3150 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3151 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155
3156 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003157 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3160 regex_t *preg;
3161 if (curproxy == &defproxy) {
3162 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003166 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003168
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 if (*(args[1]) == 0) {
3170 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174
3175 preg = calloc(1, sizeof(regex_t));
3176 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3177 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181
3182 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003183 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003185 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3186 regex_t *preg;
3187 if (curproxy == &defproxy) {
3188 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003191 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003192 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003194
Willy Tarreaub8750a82006-09-03 09:56:00 +02003195 if (*(args[1]) == 0) {
3196 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003199 }
3200
3201 preg = calloc(1, sizeof(regex_t));
3202 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3203 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003206 }
3207
3208 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003209 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 else if (!strcmp(args[0], "reqadd")) { /* add request header */
3212 if (curproxy == &defproxy) {
3213 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003217 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219
3220 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
3221 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 }
3225
3226 if (*(args[1]) == 0) {
3227 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 }
3231
3232 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02003233 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
3235 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3236 regex_t *preg;
3237
3238 if (*(args[1]) == 0 || *(args[2]) == 0) {
3239 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003244 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003246
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 preg = calloc(1, sizeof(regex_t));
3248 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3249 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 }
3253
3254 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3255 if (err) {
3256 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3257 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003261 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 }
3263 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
3264 regex_t *preg;
3265 if (curproxy == &defproxy) {
3266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003270 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003271 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003272
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 if (*(args[1]) == 0) {
3274 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
3278
3279 preg = calloc(1, sizeof(regex_t));
3280 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3281 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
3285
3286 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3287 if (err) {
3288 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3289 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293 }
3294 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
3295 regex_t *preg;
3296 if (curproxy == &defproxy) {
3297 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003301 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003303
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 if (*(args[1]) == 0) {
3305 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 }
3309
3310 preg = calloc(1, sizeof(regex_t));
3311 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3312 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
3316
3317 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3318 if (err) {
3319 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3320 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
3324 }
3325 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
3326 regex_t *preg;
3327 if (curproxy == &defproxy) {
3328 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003332 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334
3335 if (*(args[1]) == 0 || *(args[2]) == 0) {
3336 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341
3342 preg = calloc(1, sizeof(regex_t));
3343 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3344 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
3348
3349 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3350 if (err) {
3351 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3352 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356 }
3357 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
3358 regex_t *preg;
3359 if (curproxy == &defproxy) {
3360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003364 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003366
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 if (*(args[1]) == 0) {
3368 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
3372
3373 preg = calloc(1, sizeof(regex_t));
3374 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3375 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
3379
3380 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
3381 if (err) {
3382 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3383 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 }
3387 }
3388 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
3389 regex_t *preg;
3390 if (curproxy == &defproxy) {
3391 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003395 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003397
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 if (*(args[1]) == 0) {
3399 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403
3404 preg = calloc(1, sizeof(regex_t));
3405 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3406 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
3410
3411 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
3412 if (err) {
3413 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3414 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 }
3418 }
3419 else if (!strcmp(args[0], "rspadd")) { /* add response header */
3420 if (curproxy == &defproxy) {
3421 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003425 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427
3428 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
3429 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
3433
3434 if (*(args[1]) == 0) {
3435 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
3439
3440 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
3441 }
3442 else if (!strcmp(args[0], "errorloc") ||
3443 !strcmp(args[0], "errorloc302") ||
3444 !strcmp(args[0], "errorloc303")) { /* error location */
3445 int errnum, errlen;
3446 char *err;
3447
Willy Tarreau977b8e42006-12-29 14:19:17 +01003448 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003450
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003452 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
3456
3457 errnum = atol(args[1]);
3458 if (!strcmp(args[0], "errorloc303")) {
3459 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
3460 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
3461 } else {
3462 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3463 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3464 }
3465
Willy Tarreau0f772532006-12-23 20:51:41 +01003466 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3467 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003468 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003469 curproxy->errmsg[rc].str = err;
3470 curproxy->errmsg[rc].len = errlen;
3471 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003474
3475 if (rc >= HTTP_ERR_SIZE) {
3476 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3477 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 free(err);
3479 }
3480 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003481 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3482 int errnum, errlen, fd;
3483 char *err;
3484 struct stat stat;
3485
3486 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003487 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003488
3489 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003490 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003493 }
3494
3495 fd = open(args[2], O_RDONLY);
3496 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3497 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3498 file, linenum, args[2], args[1]);
3499 if (fd >= 0)
3500 close(fd);
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
Willy Tarreau27a674e2009-08-17 07:23:33 +02003505 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02003506 errlen = stat.st_size;
3507 } else {
3508 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02003509 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02003511 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003512 }
3513
3514 err = malloc(errlen); /* malloc() must succeed during parsing */
3515 errnum = read(fd, err, errlen);
3516 if (errnum != errlen) {
3517 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3518 file, linenum, args[2], args[1]);
3519 close(fd);
3520 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003523 }
3524 close(fd);
3525
3526 errnum = atol(args[1]);
3527 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3528 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003529 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003530 curproxy->errmsg[rc].str = err;
3531 curproxy->errmsg[rc].len = errlen;
3532 break;
3533 }
3534 }
3535
3536 if (rc >= HTTP_ERR_SIZE) {
3537 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3538 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02003539 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02003540 free(err);
3541 }
3542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003544 struct cfg_kw_list *kwl;
3545 int index;
3546
3547 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3548 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3549 if (kwl->kw[index].section != CFG_LISTEN)
3550 continue;
3551 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3552 /* prepare error message just in case */
3553 snprintf(trash, sizeof(trash),
3554 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003555 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3556 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003557 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003560 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003561 else if (rc > 0) {
3562 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_WARN;
3564 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02003565 }
Willy Tarreau93893792009-07-23 13:19:11 +02003566 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003567 }
3568 }
3569 }
3570
Willy Tarreau6daf3432008-01-22 16:44:08 +01003571 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003574 }
Willy Tarreau93893792009-07-23 13:19:11 +02003575 out:
3576 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577}
3578
3579
3580/*
3581 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02003582 * Returns the error code, 0 if OK, or any combination of :
3583 * - ERR_ABORT: must abort ASAP
3584 * - ERR_FATAL: we can continue parsing but not start the service
3585 * - ERR_WARN: a warning has been emitted
3586 * - ERR_ALERT: an alert has been emitted
3587 * Only the two first ones can stop processing, the two others are just
3588 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003590int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003592 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 FILE *f;
3594 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02003596 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 if ((f=fopen(file,"r")) == NULL)
3599 return -1;
3600
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003601 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003602 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003603 char *end;
3604 char *args[MAX_LINE_ARGS + 1];
3605 char *line = thisline;
3606
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 linenum++;
3608
3609 end = line + strlen(line);
3610
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003611 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3612 /* Check if we reached the limit and the last char is not \n.
3613 * Watch out for the last line without the terminating '\n'!
3614 */
3615 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003616 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003618 }
3619
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003621 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 line++;
3623
3624 arg = 0;
3625 args[arg] = line;
3626
3627 while (*line && arg < MAX_LINE_ARGS) {
3628 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3629 * C equivalent value. Other combinations left unchanged (eg: \1).
3630 */
3631 if (*line == '\\') {
3632 int skip = 0;
3633 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3634 *line = line[1];
3635 skip = 1;
3636 }
3637 else if (line[1] == 'r') {
3638 *line = '\r';
3639 skip = 1;
3640 }
3641 else if (line[1] == 'n') {
3642 *line = '\n';
3643 skip = 1;
3644 }
3645 else if (line[1] == 't') {
3646 *line = '\t';
3647 skip = 1;
3648 }
3649 else if (line[1] == 'x') {
3650 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3651 unsigned char hex1, hex2;
3652 hex1 = toupper(line[2]) - '0';
3653 hex2 = toupper(line[3]) - '0';
3654 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3655 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3656 *line = (hex1<<4) + hex2;
3657 skip = 3;
3658 }
3659 else {
3660 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 }
3663 }
3664 if (skip) {
3665 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3666 end -= skip;
3667 }
3668 line++;
3669 }
3670 else if (*line == '#' || *line == '\n' || *line == '\r') {
3671 /* end of string, end of loop */
3672 *line = 0;
3673 break;
3674 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003675 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003677 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003678 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003679 line++;
3680 args[++arg] = line;
3681 }
3682 else {
3683 line++;
3684 }
3685 }
3686
3687 /* empty line */
3688 if (!**args)
3689 continue;
3690
Willy Tarreau540abe42007-05-02 20:50:16 +02003691 /* zero out remaining args and ensure that at least one entry
3692 * is zeroed out.
3693 */
3694 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 args[arg] = line;
3696 }
3697
Willy Tarreau3842f002009-06-14 11:39:52 +02003698 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003699 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02003700 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003701 for (arg=0; *args[arg+1]; arg++)
3702 args[arg] = args[arg+1]; // shift args after inversion
3703 }
Willy Tarreau3842f002009-06-14 11:39:52 +02003704 else if (!strcmp(args[0], "default")) {
3705 kwm = KWM_DEF;
3706 for (arg=0; *args[arg+1]; arg++)
3707 args[arg] = args[arg+1]; // shift args after inversion
3708 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003709
Willy Tarreau3842f002009-06-14 11:39:52 +02003710 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
3711 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003713 }
3714
Willy Tarreau977b8e42006-12-29 14:19:17 +01003715 if (!strcmp(args[0], "listen") ||
3716 !strcmp(args[0], "frontend") ||
3717 !strcmp(args[0], "backend") ||
3718 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003719 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003721 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003722 cursection = strdup(args[0]);
3723 }
3724 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003726 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003727 cursection = strdup(args[0]);
3728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 /* else it's a section keyword */
3730
3731 switch (confsect) {
3732 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 break;
3735 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02003736 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 break;
3738 default:
3739 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 }
Willy Tarreau058e9072009-07-20 09:30:05 +02003742
3743 if (err_code & ERR_ABORT)
3744 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003746 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003747 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003748 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02003749 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003750}
3751
Willy Tarreaubb925012009-07-23 13:36:36 +02003752/*
3753 * Returns the error code, 0 if OK, or any combination of :
3754 * - ERR_ABORT: must abort ASAP
3755 * - ERR_FATAL: we can continue parsing but not start the service
3756 * - ERR_WARN: a warning has been emitted
3757 * - ERR_ALERT: an alert has been emitted
3758 * Only the two first ones can stop processing, the two others are just
3759 * indicators.
3760 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003761int check_config_validity()
3762{
3763 int cfgerr = 0;
3764 struct proxy *curproxy = NULL;
3765 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02003766 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767
3768 /*
3769 * Now, check for the integrity of all that we have collected.
3770 */
3771
3772 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003773 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003775 /* first, we will invert the proxy list order */
3776 curproxy = NULL;
3777 while (proxy) {
3778 struct proxy *next;
3779
3780 next = proxy->next;
3781 proxy->next = curproxy;
3782 curproxy = proxy;
3783 if (!next)
3784 break;
3785 proxy = next;
3786 }
3787
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003789 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 }
3793
3794 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003795 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003796 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003797
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003799 /* ensure we don't keep listeners uselessly bound */
3800 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003801 curproxy = curproxy->next;
3802 continue;
3803 }
3804
Willy Tarreauff01a212009-03-15 13:46:16 +01003805 switch (curproxy->mode) {
3806 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003807 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003808 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003809 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3810 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003811 cfgerr++;
3812 }
3813
3814 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003815 Warning("config : servers will be ignored for %s '%s'.\n",
3816 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003817 break;
3818
3819 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003820 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01003821 break;
3822
3823 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02003824 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01003825 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003826 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
3827 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01003828 cfgerr++;
3829 }
3830 break;
3831 }
3832
3833 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003834 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
3835 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 cfgerr++;
3837 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003838
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003839 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3840 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3841 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003842 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
3843 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003844 cfgerr++;
3845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003847 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003848 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
3849 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003850 cfgerr++;
3851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003853 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003854 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
3855 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003856 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003857 }
3858 }
3859 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3860 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3861 /* If no LB algo is set in a backend, and we're not in
3862 * transparent mode, dispatch mode nor proxy mode, we
3863 * want to use balance roundrobin by default.
3864 */
3865 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3866 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003869
Willy Tarreau82936582007-11-30 15:20:09 +01003870 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3871 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003872 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3873 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003874 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01003875 }
3876
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003877 /* if a default backend was specified, let's find it */
3878 if (curproxy->defbe.name) {
3879 struct proxy *target;
3880
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003881 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3882 if (!target) {
3883 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3884 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003885 cfgerr++;
3886 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003887 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3888 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02003889 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003890 } else {
3891 free(curproxy->defbe.name);
3892 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003893 /* we force the backend to be present on at least all of
3894 * the frontend's processes.
3895 */
3896 target->bind_proc = curproxy->bind_proc ?
3897 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 }
3899 }
3900
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003901 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003902 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3903 /* map jump target for ACT_SETBE in req_rep chain */
3904 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003905 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003906 struct proxy *target;
3907
Willy Tarreaua496b602006-12-17 23:15:24 +01003908 if (exp->action != ACT_SETBE)
3909 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003910
3911 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3912 if (!target) {
3913 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3914 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003915 cfgerr++;
3916 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003917 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3918 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003919 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003920 } else {
3921 free((void *)exp->replace);
3922 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003923 /* we force the backend to be present on at least all of
3924 * the frontend's processes.
3925 */
3926 target->bind_proc = curproxy->bind_proc ?
3927 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003928 }
3929 }
3930 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003931
3932 /* find the target proxy for 'use_backend' rules */
3933 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003934 struct proxy *target;
3935
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003936 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003937
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003938 if (!target) {
3939 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3940 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003941 cfgerr++;
3942 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003943 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3944 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003945 cfgerr++;
3946 } else {
3947 free((void *)rule->be.name);
3948 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003949 /* we force the backend to be present on at least all of
3950 * the frontend's processes.
3951 */
3952 target->bind_proc = curproxy->bind_proc ?
3953 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003954 }
3955 }
3956
Willy Tarreau2738a142006-07-08 17:28:09 +02003957 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003958 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003959 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003960 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003961 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003962 " | While not properly invalid, you will certainly encounter various problems\n"
3963 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003964 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02003965 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02003966 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02003967 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003968
Willy Tarreau1fa31262007-12-03 00:36:16 +01003969 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3970 * We must still support older configurations, so let's find out whether those
3971 * parameters have been set or must be copied from contimeouts.
3972 */
3973 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003974 if (!curproxy->timeout.tarpit ||
3975 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003976 /* tarpit timeout not set. We search in the following order:
3977 * default.tarpit, curr.connect, default.connect.
3978 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003979 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003980 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003981 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003982 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003983 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003984 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003985 }
3986 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003987 (!curproxy->timeout.queue ||
3988 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003989 /* queue timeout not set. We search in the following order:
3990 * default.queue, curr.connect, default.connect.
3991 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003992 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003993 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003994 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003995 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003996 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003997 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003998 }
3999 }
4000
Willy Tarreauf3c69202006-07-09 16:42:34 +02004001 if (curproxy->options & PR_O_SSL3_CHK) {
4002 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4003 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4004 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4005 }
4006
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004007 /* The small pools required for the capture lists */
4008 if (curproxy->nb_req_cap)
4009 curproxy->req_cap_pool = create_pool("ptrcap",
4010 curproxy->nb_req_cap * sizeof(char *),
4011 MEM_F_SHARED);
4012 if (curproxy->nb_rsp_cap)
4013 curproxy->rsp_cap_pool = create_pool("ptrcap",
4014 curproxy->nb_rsp_cap * sizeof(char *),
4015 MEM_F_SHARED);
4016
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004017 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4018 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4019 MEM_F_SHARED);
4020
Willy Tarreau86034312006-12-29 00:10:33 +01004021 /* for backwards compatibility with "listen" instances, if
4022 * fullconn is not set but maxconn is set, then maxconn
4023 * is used.
4024 */
4025 if (!curproxy->fullconn)
4026 curproxy->fullconn = curproxy->maxconn;
4027
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028 /* first, we will invert the servers list order */
4029 newsrv = NULL;
4030 while (curproxy->srv) {
4031 struct server *next;
4032
4033 next = curproxy->srv->next;
4034 curproxy->srv->next = newsrv;
4035 newsrv = curproxy->srv;
4036 if (!next)
4037 break;
4038 curproxy->srv = next;
4039 }
4040
Willy Tarreau20697042007-11-15 23:26:18 +01004041 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004042 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043
Willy Tarreaub625a082007-11-26 01:15:43 +01004044 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01004045 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01004046 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01004047 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
4048 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01004049 else
4050 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051
4052 if (curproxy->options & PR_O_LOGASAP)
4053 curproxy->to_log &= ~LW_BYTES;
4054
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004055 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4056 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4057 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4058 proxy_type_str(curproxy), curproxy->id);
4059 err_code |= ERR_WARN;
4060 }
4061
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004063 * ensure that we're not cross-dressing a TCP server into HTTP.
4064 */
4065 newsrv = curproxy->srv;
4066 while (newsrv != NULL) {
4067 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004068 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4069 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004070 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004071 }
4072 newsrv = newsrv->next;
4073 }
4074
4075 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 * If this server supports a maxconn parameter, it needs a dedicated
4077 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004078 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079 */
4080 newsrv = curproxy->srv;
4081 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004082 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 /* Only 'minconn' was specified, or it was higher than or equal
4084 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4085 * this will avoid further useless expensive computations.
4086 */
4087 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004088 } else if (newsrv->maxconn && !newsrv->minconn) {
4089 /* minconn was not specified, so we set it to maxconn */
4090 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004091 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004092 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4093 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004094 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004095 }
4096
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004097 if (newsrv->trackit) {
4098 struct proxy *px;
4099 struct server *srv;
4100 char *pname, *sname;
4101
4102 pname = newsrv->trackit;
4103 sname = strrchr(pname, '/');
4104
4105 if (sname)
4106 *sname++ = '\0';
4107 else {
4108 sname = pname;
4109 pname = NULL;
4110 }
4111
4112 if (pname) {
4113 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
4114 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004115 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4116 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004117 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004118 cfgerr++;
4119 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004120 }
4121 } else
4122 px = curproxy;
4123
4124 srv = findserver(px, sname);
4125 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004126 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4127 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004128 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004129 cfgerr++;
4130 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004131 }
4132
4133 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004134 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004135 "tracing as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004136 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004137 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004138 cfgerr++;
4139 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004140 }
4141
4142 if (curproxy != px &&
4143 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004144 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004145 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004146 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004147 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004148 cfgerr++;
4149 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004150 }
4151
4152 newsrv->tracked = srv;
4153 newsrv->tracknext = srv->tracknext;
4154 srv->tracknext = newsrv;
4155
4156 free(newsrv->trackit);
4157 }
Willy Tarreaubb925012009-07-23 13:36:36 +02004158 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 newsrv = newsrv->next;
4160 }
4161
Willy Tarreauc1a21672009-08-16 22:37:44 +02004162 if (curproxy->cap & PR_CAP_FE) {
4163 if (curproxy->tcp_req.inspect_delay ||
4164 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
4165 curproxy->fe_req_ana |= AN_REQ_INSPECT;
4166
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004167 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004168 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004169 curproxy->fe_rsp_ana |= AN_RTR_HTTP_HDR;
4170 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004171
4172 /* both TCP and HTTP must check switching rules */
4173 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
4174 }
4175
4176 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004177 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02004178 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02004179 curproxy->be_rsp_ana |= AN_RTR_HTTP_HDR;
4180 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02004181
4182 /* If the backend does requires RDP cookie persistence, we have to
4183 * enable the corresponding analyser.
4184 */
4185 if (curproxy->options2 & PR_O2_RDPC_PRST)
4186 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
4187 }
4188
Willy Tarreaue6b98942007-10-29 01:09:36 +01004189 /* adjust this proxy's listeners */
4190 listener = curproxy->listen;
4191 while (listener) {
4192 if (curproxy->options & PR_O_TCP_NOLING)
4193 listener->options |= LI_O_NOLINGER;
4194 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004195 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004196 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004197 listener->accept = event_accept;
4198 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004199 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02004200 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01004201
Willy Tarreau9ea05a72009-06-14 12:07:01 +02004202 /* smart accept mode is automatic in HTTP mode */
4203 if ((curproxy->options2 & PR_O2_SMARTACC) ||
4204 (curproxy->mode == PR_MODE_HTTP &&
4205 !(curproxy->no_options2 & PR_O2_SMARTACC)))
4206 listener->options |= LI_O_NOQUICKACK;
4207
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02004208 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01004209 listener = listener->next;
4210 }
4211
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 curproxy = curproxy->next;
4213 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004214
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004215 /*
4216 * Recount currently required checks.
4217 */
4218
4219 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
4220 int optnum;
4221
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004222 for (optnum = 0; cfg_opts[optnum].name; optnum++)
4223 if (curproxy->options & cfg_opts[optnum].val)
4224 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004225
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004226 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
4227 if (curproxy->options2 & cfg_opts2[optnum].val)
4228 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004229 }
4230
Willy Tarreaubb925012009-07-23 13:36:36 +02004231 if (cfgerr > 0)
4232 err_code |= ERR_ALERT | ERR_FATAL;
4233 out:
4234 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235}
4236
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004237/*
4238 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
4239 * parsing sessions.
4240 */
4241void cfg_register_keywords(struct cfg_kw_list *kwl)
4242{
4243 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
4244}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004246/*
4247 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
4248 */
4249void cfg_unregister_keywords(struct cfg_kw_list *kwl)
4250{
4251 LIST_DEL(&kwl->list);
4252 LIST_INIT(&kwl->list);
4253}
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254
4255/*
4256 * Local variables:
4257 * c-indent-level: 8
4258 * c-basic-offset: 8
4259 * End:
4260 */