blob: 6a4744e531f2189cd58324fcf81e3ac3ba3326d5 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreau7c669d72008-06-20 15:04:11 +02004 * Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
27#include <common/config.h>
28#include <common/memory.h>
29#include <common/standard.h>
30#include <common/time.h>
31#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020032
33#include <types/capture.h>
34#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreaueb0c6142007-05-07 00:53:22 +020036#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010038#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020040#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/httperr.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/log.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010043#include <proto/protocols.h>
44#include <proto/proto_tcp.h>
45#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010046#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010048#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/task.h>
50
51
Willy Tarreauf3c69202006-07-09 16:42:34 +020052/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
53 * ssl-hello-chk option to ensure that the remote server speaks SSL.
54 *
55 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
56 */
57const char sslv3_client_hello_pkt[] = {
58 "\x16" /* ContentType : 0x16 = Hanshake */
59 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
60 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
61 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
62 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
63 "\x03\x00" /* Hello Version : 0x0300 = v3 */
64 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
65 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
66 "\x00" /* Session ID length : empty (no session ID) */
67 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
68 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
69 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
70 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
71 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
72 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
73 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
74 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
75 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
76 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
77 "\x00\x38" "\x00\x39" "\x00\x3A"
78 "\x01" /* Compression Length : 0x01 = 1 byte for types */
79 "\x00" /* Compression Type : 0x00 = NULL compression */
80};
81
Willy Tarreau13943ab2006-12-31 00:24:10 +010082/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +010083struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +010084 const char *name;
85 unsigned int val;
86 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +010087 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +010088};
89
90/* proxy->options */
91static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +010092{
Willy Tarreau4fee4e92007-01-06 21:09:17 +010093 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010094 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010095 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +010096 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +010097 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
98 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
99 { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 },
100 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
101 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
102 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
103 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
104 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100105 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100106 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
107 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100108#ifdef CONFIG_HAP_TCPSPLICE
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100109 { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM },
110#endif
111#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100112 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100113#endif
114
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100115 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116};
117
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118/* proxy->options2 */
119static const struct cfg_opt cfg_opts2[] =
120{
121#ifdef CONFIG_HAP_LINUX_SPLICE
122 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
123 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
124 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
125#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200126 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
127 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200128 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
129 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100130 { NULL, 0, 0, 0 }
131};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132
Willy Tarreau6daf3432008-01-22 16:44:08 +0100133static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200134static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
135int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100136int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200137
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200138/* List head of all known configuration keywords */
139static struct cfg_kw_list cfg_keywords = {
140 .list = LIST_HEAD_INIT(cfg_keywords.list)
141};
142
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143/*
144 * converts <str> to a list of listeners which are dynamically allocated.
145 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
146 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
147 * - <port> is a numerical port from 1 to 65535 ;
148 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
149 * This can be repeated as many times as necessary, separated by a coma.
150 * The <tail> argument is a pointer to a current list which should be appended
151 * to the tail of the new list. The pointer to the new list is returned.
152 */
153static struct listener *str2listener(char *str, struct listener *tail)
154{
155 struct listener *l;
156 char *c, *next, *range, *dupstr;
157 int port, end;
158
159 next = dupstr = strdup(str);
160
161 while (next && *next) {
162 struct sockaddr_storage ss;
163
164 str = next;
165 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100166 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167 *next++ = 0;
168 }
169
170 /* 2) look for the addr/port delimiter, it's the last colon. */
171 if ((range = strrchr(str, ':')) == NULL) {
172 Alert("Missing port number: '%s'\n", str);
173 goto fail;
174 }
175
176 *range++ = 0;
177
178 if (strrchr(str, ':') != NULL) {
179 /* IPv6 address contains ':' */
180 memset(&ss, 0, sizeof(ss));
181 ss.ss_family = AF_INET6;
182
183 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
184 Alert("Invalid server address: '%s'\n", str);
185 goto fail;
186 }
187 }
188 else {
189 memset(&ss, 0, sizeof(ss));
190 ss.ss_family = AF_INET;
191
192 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
193 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
194 }
195 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
196 struct hostent *he;
197
198 if ((he = gethostbyname(str)) == NULL) {
199 Alert("Invalid server name: '%s'\n", str);
200 goto fail;
201 }
202 else
203 ((struct sockaddr_in *)&ss)->sin_addr =
204 *(struct in_addr *) *(he->h_addr_list);
205 }
206 }
207
208 /* 3) look for the port-end delimiter */
209 if ((c = strchr(range, '-')) != NULL) {
210 *c++ = 0;
211 end = atol(c);
212 }
213 else {
214 end = atol(range);
215 }
216
217 port = atol(range);
218
219 if (port < 1 || port > 65535) {
220 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
221 goto fail;
222 }
223
224 if (end < 1 || end > 65535) {
225 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
226 goto fail;
227 }
228
229 for (; port <= end; port++) {
230 l = (struct listener *)calloc(1, sizeof(struct listener));
231 l->next = tail;
232 tail = l;
233
234 l->fd = -1;
235 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100236 l->state = LI_INIT;
237
238 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100240 tcpv6_add_listener(l);
241 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100243 tcpv4_add_listener(l);
244 }
245 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246 } /* end for(port) */
247 } /* end while(next) */
248 free(dupstr);
249 return tail;
250 fail:
251 free(dupstr);
252 return NULL;
253}
254
Willy Tarreau977b8e42006-12-29 14:19:17 +0100255/*
256 * Sends a warning if proxy <proxy> does not have at least one of the
257 * capabilities in <cap>. An optionnal <hint> may be added at the end
258 * of the warning to help the user. Returns 1 if a warning was emitted
259 * or 0 if the condition is valid.
260 */
261int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
262{
263 char *msg;
264
265 switch (cap) {
266 case PR_CAP_BE: msg = "no backend"; break;
267 case PR_CAP_FE: msg = "no frontend"; break;
268 case PR_CAP_RS: msg = "no ruleset"; break;
269 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
270 default: msg = "not enough"; break;
271 }
272
273 if (!(proxy->cap & cap)) {
274 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100275 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100276 return 1;
277 }
278 return 0;
279}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280
Willy Tarreau61d18892009-03-31 10:49:21 +0200281/* Report a warning if a rule is placed after a 'block' rule.
282 * Return 1 if the warning has been emitted, otherwise 0.
283 */
284int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
285{
286 if (!LIST_ISEMPTY(&proxy->block_cond)) {
287 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
288 file, line, arg);
289 return 1;
290 }
291 return 0;
292}
293
294/* Report a warning if a rule is placed after a reqrewrite rule.
295 * Return 1 if the warning has been emitted, otherwise 0.
296 */
297int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
298{
299 if (proxy->req_exp) {
300 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
301 file, line, arg);
302 return 1;
303 }
304 return 0;
305}
306
307/* Report a warning if a rule is placed after a reqadd rule.
308 * Return 1 if the warning has been emitted, otherwise 0.
309 */
310int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
311{
312 if (proxy->nb_reqadd) {
313 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
314 file, line, arg);
315 return 1;
316 }
317 return 0;
318}
319
320/* Report a warning if a rule is placed after a redirect rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
323int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
324{
325 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a 'use_backend' rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
336int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
337{
338 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* report a warning if a block rule is dangerously placed */
347int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
348{
349 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
350 warnif_rule_after_reqadd(proxy, file, line, arg) ||
351 warnif_rule_after_redirect(proxy, file, line, arg) ||
352 warnif_rule_after_use_backend(proxy, file, line, arg);
353}
354
355/* report a warning if a reqxxx rule is dangerously placed */
356int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
357{
358 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
359 warnif_rule_after_redirect(proxy, file, line, arg) ||
360 warnif_rule_after_use_backend(proxy, file, line, arg);
361}
362
363/* report a warning if a reqadd rule is dangerously placed */
364int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
365{
366 return warnif_rule_after_redirect(proxy, file, line, arg) ||
367 warnif_rule_after_use_backend(proxy, file, line, arg);
368}
369
Willy Tarreaubaaee002006-06-26 02:48:02 +0200370/*
371 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
372 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100373int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200374{
375
376 if (!strcmp(args[0], "global")) { /* new section */
377 /* no option, nothing special to do */
378 return 0;
379 }
380 else if (!strcmp(args[0], "daemon")) {
381 global.mode |= MODE_DAEMON;
382 }
383 else if (!strcmp(args[0], "debug")) {
384 global.mode |= MODE_DEBUG;
385 }
386 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100387 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200388 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200389 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100390 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200391 }
392 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100393 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100396 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200397 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100398 else if (!strcmp(args[0], "nosplice")) {
399 global.tune.options &= ~GTUNE_USE_SPLICE;
400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401 else if (!strcmp(args[0], "quiet")) {
402 global.mode |= MODE_QUIET;
403 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200404 else if (!strcmp(args[0], "tune.maxpollevents")) {
405 if (global.tune.maxpollevents != 0) {
406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
407 return 0;
408 }
409 if (*(args[1]) == 0) {
410 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
411 return -1;
412 }
413 global.tune.maxpollevents = atol(args[1]);
414 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100415 else if (!strcmp(args[0], "tune.maxaccept")) {
416 if (global.tune.maxaccept != 0) {
417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
418 return 0;
419 }
420 if (*(args[1]) == 0) {
421 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
422 return -1;
423 }
424 global.tune.maxaccept = atol(args[1]);
425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200426 else if (!strcmp(args[0], "uid")) {
427 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200428 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 return 0;
430 }
431 if (*(args[1]) == 0) {
432 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
433 return -1;
434 }
435 global.uid = atol(args[1]);
436 }
437 else if (!strcmp(args[0], "gid")) {
438 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200439 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200440 return 0;
441 }
442 if (*(args[1]) == 0) {
443 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
444 return -1;
445 }
446 global.gid = atol(args[1]);
447 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200448 /* user/group name handling */
449 else if (!strcmp(args[0], "user")) {
450 struct passwd *ha_user;
451 if (global.uid != 0) {
452 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
453 return 0;
454 }
455 errno = 0;
456 ha_user = getpwnam(args[1]);
457 if (ha_user != NULL) {
458 global.uid = (int)ha_user->pw_uid;
459 }
460 else {
461 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
462 exit(1);
463 }
464 }
465 else if (!strcmp(args[0], "group")) {
466 struct group *ha_group;
467 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200468 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200469 return 0;
470 }
471 errno = 0;
472 ha_group = getgrnam(args[1]);
473 if (ha_group != NULL) {
474 global.gid = (int)ha_group->gr_gid;
475 }
476 else {
477 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
478 exit(1);
479 }
480 }
481 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "nbproc")) {
483 if (global.nbproc != 0) {
484 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
485 return 0;
486 }
487 if (*(args[1]) == 0) {
488 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
489 return -1;
490 }
491 global.nbproc = atol(args[1]);
492 }
493 else if (!strcmp(args[0], "maxconn")) {
494 if (global.maxconn != 0) {
495 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
496 return 0;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
500 return -1;
501 }
502 global.maxconn = atol(args[1]);
503#ifdef SYSTEM_MAXCONN
504 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
505 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
506 global.maxconn = DEFAULT_MAXCONN;
507 }
508#endif /* SYSTEM_MAXCONN */
509 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100510 else if (!strcmp(args[0], "maxpipes")) {
511 if (global.maxpipes != 0) {
512 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
513 return 0;
514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
517 return -1;
518 }
519 global.maxpipes = atol(args[1]);
520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "ulimit-n")) {
522 if (global.rlimit_nofile != 0) {
523 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
524 return 0;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
528 return -1;
529 }
530 global.rlimit_nofile = atol(args[1]);
531 }
532 else if (!strcmp(args[0], "chroot")) {
533 if (global.chroot != NULL) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
535 return 0;
536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
539 return -1;
540 }
541 global.chroot = strdup(args[1]);
542 }
543 else if (!strcmp(args[0], "pidfile")) {
544 if (global.pidfile != NULL) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
546 return 0;
547 }
548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
550 return -1;
551 }
552 global.pidfile = strdup(args[1]);
553 }
554 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100555 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556 int facility, level;
557
558 if (*(args[1]) == 0 || *(args[2]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
560 return -1;
561 }
562
563 facility = get_log_facility(args[2]);
564 if (facility < 0) {
565 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
566 exit(1);
567 }
568
569 level = 7; /* max syslog level = debug */
570 if (*(args[3])) {
571 level = get_log_level(args[3]);
572 if (level < 0) {
573 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
574 exit(1);
575 }
576 }
577
Robert Tsai81ae1952007-12-05 10:47:29 +0100578 if (args[1][0] == '/') {
579 logsrv.u.addr.sa_family = AF_UNIX;
580 logsrv.u.un = *str2sun(args[1]);
581 } else {
582 logsrv.u.addr.sa_family = AF_INET;
583 logsrv.u.in = *str2sa(args[1]);
584 if (!logsrv.u.in.sin_port)
585 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587
588 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100589 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 global.logfac1 = facility;
591 global.loglev1 = level;
592 }
593 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100594 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 global.logfac2 = facility;
596 global.loglev2 = level;
597 }
598 else {
599 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
600 return -1;
601 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200602 }
603 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
604 if (global.spread_checks != 0) {
605 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
606 return 0;
607 }
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
610 return -1;
611 }
612 global.spread_checks = atol(args[1]);
613 if (global.spread_checks < 0 || global.spread_checks > 50) {
614 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
615 return -1;
616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200619 struct cfg_kw_list *kwl;
620 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200621 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200622
623 list_for_each_entry(kwl, &cfg_keywords.list, list) {
624 for (index = 0; kwl->kw[index].kw != NULL; index++) {
625 if (kwl->kw[index].section != CFG_GLOBAL)
626 continue;
627 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
628 /* prepare error message just in case */
629 snprintf(trash, sizeof(trash),
630 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200631 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
632 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200633 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
634 return -1;
635 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200636 else if (rc > 0) {
637 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
638 return 0;
639 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200640 return 0;
641 }
642 }
643 }
644
Willy Tarreaubaaee002006-06-26 02:48:02 +0200645 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
646 return -1;
647 }
648 return 0;
649}
650
651
652static void init_default_instance()
653{
654 memset(&defproxy, 0, sizeof(defproxy));
655 defproxy.mode = PR_MODE_TCP;
656 defproxy.state = PR_STNEW;
657 defproxy.maxconn = cfg_maxpconn;
658 defproxy.conn_retries = CONN_RETRIES;
659 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200660
661 LIST_INIT(&defproxy.pendconns);
662 LIST_INIT(&defproxy.acl);
663 LIST_INIT(&defproxy.block_cond);
664 LIST_INIT(&defproxy.mon_fail_cond);
665 LIST_INIT(&defproxy.switching_rules);
666
Willy Tarreau3a70f942008-02-15 11:15:34 +0100667 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668}
669
670/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100671 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
672 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100674int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675{
676 static struct proxy *curproxy = NULL;
677 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200678 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100679 int rc;
680 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681
Willy Tarreau977b8e42006-12-29 14:19:17 +0100682 if (!strcmp(args[0], "listen"))
683 rc = PR_CAP_LISTEN;
684 else if (!strcmp(args[0], "frontend"))
685 rc = PR_CAP_FE | PR_CAP_RS;
686 else if (!strcmp(args[0], "backend"))
687 rc = PR_CAP_BE | PR_CAP_RS;
688 else if (!strcmp(args[0], "ruleset"))
689 rc = PR_CAP_RS;
690 else
691 rc = PR_CAP_NONE;
692
693 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 if (!*args[1]) {
695 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
696 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
697 file, linenum, args[0]);
698 return -1;
699 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200700
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100701 err = invalid_char(args[1]);
702 if (err) {
703 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
704 file, linenum, *err, args[0], args[1]);
705 return -1;
706 }
707
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200708 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
709 /*
710 * If there are two proxies with the same name only following
711 * combinations are allowed:
712 *
713 * listen backend frontend ruleset
714 * listen - - - -
715 * backend - - OK -
716 * frontend - OK - -
717 * ruleset - - - -
718 */
719
720 if (!strcmp(curproxy->id, args[1]) &&
721 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
722 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100723 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
724 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200725 }
726 }
727
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
729 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
730 return -1;
731 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100732
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 curproxy->next = proxy;
734 proxy = curproxy;
735 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200736 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200737 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200738 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100739 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200740 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200741 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742
Willy Tarreauee991362007-05-14 14:37:50 +0200743 /* Timeouts are defined as -1, so we cannot use the zeroed area
744 * as a default value.
745 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100746 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200747
748 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100750 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751
752 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100753 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 curproxy->listen = str2listener(args[2], curproxy->listen);
755 if (!curproxy->listen)
756 return -1;
757 global.maxsock++;
758 }
759
760 /* set default values */
761 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100763 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100764 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100765 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200766 curproxy->except_net = defproxy.except_net;
767 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200768 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200769 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200771 if (defproxy.fwdfor_hdr_len) {
772 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
773 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
774 }
775
Willy Tarreau977b8e42006-12-29 14:19:17 +0100776 if (curproxy->cap & PR_CAP_FE) {
777 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100778 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100779 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100780
781 /* initialize error relocations */
782 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
783 if (defproxy.errmsg[rc].str)
784 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
785 }
786
787 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (curproxy->cap & PR_CAP_BE) {
791 curproxy->fullconn = defproxy.fullconn;
792 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793
Willy Tarreau977b8e42006-12-29 14:19:17 +0100794 if (defproxy.check_req)
795 curproxy->check_req = strdup(defproxy.check_req);
796 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797
Willy Tarreau977b8e42006-12-29 14:19:17 +0100798 if (defproxy.cookie_name)
799 curproxy->cookie_name = strdup(defproxy.cookie_name);
800 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100801
802 if (defproxy.url_param_name)
803 curproxy->url_param_name = strdup(defproxy.url_param_name);
804 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100805
806 if (defproxy.iface_name)
807 curproxy->iface_name = strdup(defproxy.iface_name);
808 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200810
Willy Tarreau977b8e42006-12-29 14:19:17 +0100811 if (curproxy->cap & PR_CAP_RS) {
812 if (defproxy.capture_name)
813 curproxy->capture_name = strdup(defproxy.capture_name);
814 curproxy->capture_namelen = defproxy.capture_namelen;
815 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817
Willy Tarreau977b8e42006-12-29 14:19:17 +0100818 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100819 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100820 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100821 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100822 curproxy->uri_auth = defproxy.uri_auth;
823 curproxy->mon_net = defproxy.mon_net;
824 curproxy->mon_mask = defproxy.mon_mask;
825 if (defproxy.monitor_uri)
826 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
827 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100828 if (defproxy.defbe.name)
829 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100830 }
831
832 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100833 curproxy->timeout.connect = defproxy.timeout.connect;
834 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100835 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100836 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100837 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100838 curproxy->source_addr = defproxy.source_addr;
839 }
840
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 curproxy->mode = defproxy.mode;
842 curproxy->logfac1 = defproxy.logfac1;
843 curproxy->logsrv1 = defproxy.logsrv1;
844 curproxy->loglev1 = defproxy.loglev1;
845 curproxy->logfac2 = defproxy.logfac2;
846 curproxy->logsrv2 = defproxy.logsrv2;
847 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100849 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
850 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200851
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 return 0;
853 }
854 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
855 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100856 /* FIXME-20070101: we should do this too at the end of the
857 * config parsing to free all default values.
858 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200859 free(defproxy.check_req);
860 free(defproxy.cookie_name);
861 free(defproxy.url_param_name);
862 free(defproxy.capture_name);
863 free(defproxy.monitor_uri);
864 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100865 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200866 free(defproxy.fwdfor_hdr_name);
867 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100868
Willy Tarreaua534fea2008-08-03 12:19:50 +0200869 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
870 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100871
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 /* we cannot free uri_auth because it might already be used */
873 init_default_instance();
874 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100875 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 return 0;
877 }
878 else if (curproxy == NULL) {
879 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
880 return -1;
881 }
882
Willy Tarreau977b8e42006-12-29 14:19:17 +0100883
884 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100886 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100887 int cur_arg;
888
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 if (curproxy == &defproxy) {
890 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
891 return -1;
892 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100893 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
894 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895
896 if (strchr(args[1], ':') == NULL) {
897 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
898 file, linenum, args[0]);
899 return -1;
900 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100901
902 last_listen = curproxy->listen;
903 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 if (!curproxy->listen)
905 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100906
907 cur_arg = 2;
908 while (*(args[cur_arg])) {
909 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
910#ifdef SO_BINDTODEVICE
911 struct listener *l;
912
913 if (!*args[cur_arg + 1]) {
914 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
915 file, linenum, args[0]);
916 return -1;
917 }
918
919 for (l = curproxy->listen; l != last_listen; l = l->next)
920 l->interface = strdup(args[cur_arg + 1]);
921
922 global.last_checks |= LSTCHK_NETADM;
923
924 cur_arg += 2;
925 continue;
926#else
927 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
928 file, linenum, args[0], args[cur_arg]);
929 return -1;
930#endif
931 }
932 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100933#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100934 struct listener *l;
935
936 for (l = curproxy->listen; l != last_listen; l = l->next)
937 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100938
939 cur_arg ++;
940 continue;
941#else
942 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
943 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100944 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100945#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100946 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100947 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100948 file, linenum, args[0]);
949 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 global.maxsock++;
952 return 0;
953 }
954 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
955 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
956 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
957 file, linenum, args[0]);
958 return -1;
959 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100960 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
961 return 0;
962
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 /* flush useless bits */
964 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
965 return 0;
966 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200967 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
969 return 0;
970
Willy Tarreau1c47f852006-07-09 08:22:27 +0200971 if (!*args[1]) {
972 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
973 file, linenum, args[0]);
974 return -1;
975 }
976
Willy Tarreaua534fea2008-08-03 12:19:50 +0200977 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100978 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200979 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100980 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200981 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
982
983 return 0;
984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
986 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
987 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
988 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
989 else {
990 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
991 return -1;
992 }
993 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100994 else if (!strcmp(args[0], "id")) {
995 struct proxy *target;
996
997 if (curproxy == &defproxy) {
998 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
999 file, linenum, args[0]);
1000 return -1;
1001 }
1002
1003 if (!*args[1]) {
1004 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1005 file, linenum, args[0]);
1006 return -1;
1007 }
1008
1009 curproxy->uuid = atol(args[1]);
1010
1011 if (curproxy->uuid < 1001) {
1012 Alert("parsing [%s:%d]: custom id has to be > 1000",
1013 file, linenum);
1014 return -1;
1015 }
1016
1017 for (target = proxy; target; target = target->next)
1018 if (curproxy != target && curproxy->uuid == target->uuid) {
1019 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1020 file, linenum, curproxy->id, target->id);
1021 return -1;
1022 }
1023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1025 curproxy->state = PR_STSTOPPED;
1026 }
1027 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1028 curproxy->state = PR_STNEW;
1029 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001030 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1031 int cur_arg = 1;
1032 unsigned int set = 0;
1033
1034 while (*args[cur_arg]) {
1035 int u;
1036 if (strcmp(args[cur_arg], "all") == 0) {
1037 set = 0;
1038 break;
1039 }
1040 else if (strcmp(args[cur_arg], "odd") == 0) {
1041 set |= 0x55555555;
1042 }
1043 else if (strcmp(args[cur_arg], "even") == 0) {
1044 set |= 0xAAAAAAAA;
1045 }
1046 else {
1047 u = str2uic(args[cur_arg]);
1048 if (u < 1 || u > 32) {
1049 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1050 file, linenum, args[0]);
1051 return -1;
1052 }
1053 if (u > global.nbproc) {
1054 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1055 file, linenum, args[0]);
1056 }
1057 set |= 1 << (u - 1);
1058 }
1059 cur_arg++;
1060 }
1061 curproxy->bind_proc = set;
1062 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001063 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001064 if (curproxy == &defproxy) {
1065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1066 return -1;
1067 }
1068
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001069 err = invalid_char(args[1]);
1070 if (err) {
1071 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1072 file, linenum, *err, args[1]);
1073 return -1;
1074 }
1075
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001076 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1077 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1078 file, linenum, args[1]);
1079 return -1;
1080 }
1081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1083 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1086 return 0;
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1090 file, linenum, args[0]);
1091 return -1;
1092 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001093
1094 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095 curproxy->cookie_name = strdup(args[1]);
1096 curproxy->cookie_len = strlen(curproxy->cookie_name);
1097
1098 cur_arg = 2;
1099 while (*(args[cur_arg])) {
1100 if (!strcmp(args[cur_arg], "rewrite")) {
1101 curproxy->options |= PR_O_COOK_RW;
1102 }
1103 else if (!strcmp(args[cur_arg], "indirect")) {
1104 curproxy->options |= PR_O_COOK_IND;
1105 }
1106 else if (!strcmp(args[cur_arg], "insert")) {
1107 curproxy->options |= PR_O_COOK_INS;
1108 }
1109 else if (!strcmp(args[cur_arg], "nocache")) {
1110 curproxy->options |= PR_O_COOK_NOC;
1111 }
1112 else if (!strcmp(args[cur_arg], "postonly")) {
1113 curproxy->options |= PR_O_COOK_POST;
1114 }
1115 else if (!strcmp(args[cur_arg], "prefix")) {
1116 curproxy->options |= PR_O_COOK_PFX;
1117 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001118 else if (!strcmp(args[cur_arg], "domain")) {
1119 if (!*args[cur_arg + 1]) {
1120 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1121 file, linenum, args[cur_arg]);
1122 return -1;
1123 }
1124
1125 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1126 /* rfc2109, 4.3.2 Rejecting Cookies */
1127 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1128 " dots or does not start with a dot.\n",
1129 file, linenum, args[cur_arg + 1]);
1130 return -1;
1131 }
1132
1133 err = invalid_domainchar(args[cur_arg + 1]);
1134 if (err) {
1135 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1136 file, linenum, *err, args[cur_arg + 1]);
1137 return -1;
1138 }
1139
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001140 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001141 cur_arg++;
1142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001144 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 file, linenum, args[0]);
1146 return -1;
1147 }
1148 cur_arg++;
1149 }
1150 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1151 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1152 file, linenum);
1153 return -1;
1154 }
1155
1156 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1157 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1158 file, linenum);
1159 return -1;
1160 }
1161 }/* end else if (!strcmp(args[0], "cookie")) */
1162 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
Willy Tarreau977b8e42006-12-29 14:19:17 +01001164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1165 return 0;
1166
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 if (*(args[5]) == 0) {
1168 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1169 file, linenum, args[0]);
1170 return -1;
1171 }
1172 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001173 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 curproxy->appsession_name = strdup(args[1]);
1175 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1176 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001177 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1178 if (err) {
1179 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1180 file, linenum, *err, args[0]);
1181 return -1;
1182 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001183 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001184
Willy Tarreau51041c72007-09-09 21:56:53 +02001185 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1186 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 return -1;
1188 }
1189 } /* Url App Session */
1190 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001191 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1192 return 0;
1193
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 if (*(args[4]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1197 file, linenum, args[0]);
1198 return -1;
1199 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001200 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 curproxy->capture_name = strdup(args[2]);
1202 curproxy->capture_namelen = strlen(curproxy->capture_name);
1203 curproxy->capture_len = atol(args[4]);
1204 if (curproxy->capture_len >= CAPTURE_LEN) {
1205 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1206 file, linenum, CAPTURE_LEN - 1);
1207 curproxy->capture_len = CAPTURE_LEN - 1;
1208 }
1209 curproxy->to_log |= LW_COOKIE;
1210 }
1211 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1212 struct cap_hdr *hdr;
1213
1214 if (curproxy == &defproxy) {
1215 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1216 return -1;
1217 }
1218
1219 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1220 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1221 file, linenum, args[0], args[1]);
1222 return -1;
1223 }
1224
1225 hdr = calloc(sizeof(struct cap_hdr), 1);
1226 hdr->next = curproxy->req_cap;
1227 hdr->name = strdup(args[3]);
1228 hdr->namelen = strlen(args[3]);
1229 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001230 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 hdr->index = curproxy->nb_req_cap++;
1232 curproxy->req_cap = hdr;
1233 curproxy->to_log |= LW_REQHDR;
1234 }
1235 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1236 struct cap_hdr *hdr;
1237
1238 if (curproxy == &defproxy) {
1239 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1240 return -1;
1241 }
1242
1243 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1244 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1245 file, linenum, args[0], args[1]);
1246 return -1;
1247 }
1248 hdr = calloc(sizeof(struct cap_hdr), 1);
1249 hdr->next = curproxy->rsp_cap;
1250 hdr->name = strdup(args[3]);
1251 hdr->namelen = strlen(args[3]);
1252 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001253 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001254 hdr->index = curproxy->nb_rsp_cap++;
1255 curproxy->rsp_cap = hdr;
1256 curproxy->to_log |= LW_RSPHDR;
1257 }
1258 else {
1259 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1260 file, linenum, args[0]);
1261 return -1;
1262 }
1263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001265 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1266 return 0;
1267
Willy Tarreaubaaee002006-06-26 02:48:02 +02001268 if (*(args[1]) == 0) {
1269 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1270 file, linenum, args[0]);
1271 return -1;
1272 }
1273 curproxy->conn_retries = atol(args[1]);
1274 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001275 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1276 int pol = ACL_COND_NONE;
1277 struct acl_cond *cond;
1278
Willy Tarreaub099aca2008-10-12 17:26:37 +02001279 if (curproxy == &defproxy) {
1280 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1281 return -1;
1282 }
1283
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001284 if (!strcmp(args[1], "if"))
1285 pol = ACL_COND_IF;
1286 else if (!strcmp(args[1], "unless"))
1287 pol = ACL_COND_UNLESS;
1288
1289 if (pol == ACL_COND_NONE) {
1290 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1291 file, linenum, args[0]);
1292 return -1;
1293 }
1294
1295 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1296 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1297 file, linenum);
1298 return -1;
1299 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001300 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001301 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001302 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001303 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001304 else if (!strcmp(args[0], "redirect")) {
1305 int pol = ACL_COND_NONE;
1306 struct acl_cond *cond;
1307 struct redirect_rule *rule;
1308 int cur_arg;
1309 int type = REDIRECT_TYPE_NONE;
1310 int code = 302;
1311 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001312 char *cookie = NULL;
1313 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001314 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001315
1316 cur_arg = 1;
1317 while (*(args[cur_arg])) {
1318 if (!strcmp(args[cur_arg], "location")) {
1319 if (!*args[cur_arg + 1]) {
1320 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1321 file, linenum, args[0], args[cur_arg]);
1322 return -1;
1323 }
1324
1325 type = REDIRECT_TYPE_LOCATION;
1326 cur_arg++;
1327 destination = args[cur_arg];
1328 }
1329 else if (!strcmp(args[cur_arg], "prefix")) {
1330 if (!*args[cur_arg + 1]) {
1331 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1332 file, linenum, args[0], args[cur_arg]);
1333 return -1;
1334 }
1335
1336 type = REDIRECT_TYPE_PREFIX;
1337 cur_arg++;
1338 destination = args[cur_arg];
1339 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001340 else if (!strcmp(args[cur_arg], "set-cookie")) {
1341 if (!*args[cur_arg + 1]) {
1342 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1343 file, linenum, args[0], args[cur_arg]);
1344 return -1;
1345 }
1346
1347 cur_arg++;
1348 cookie = args[cur_arg];
1349 cookie_set = 1;
1350 }
1351 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1352 if (!*args[cur_arg + 1]) {
1353 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1354 file, linenum, args[0], args[cur_arg]);
1355 return -1;
1356 }
1357
1358 cur_arg++;
1359 cookie = args[cur_arg];
1360 cookie_set = 0;
1361 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001362 else if (!strcmp(args[cur_arg],"code")) {
1363 if (!*args[cur_arg + 1]) {
1364 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1365 file, linenum, args[0]);
1366 return -1;
1367 }
1368 cur_arg++;
1369 code = atol(args[cur_arg]);
1370 if (code < 301 || code > 303) {
1371 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1372 file, linenum, args[0], code);
1373 return -1;
1374 }
1375 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001376 else if (!strcmp(args[cur_arg],"drop-query")) {
1377 flags |= REDIRECT_FLAG_DROP_QS;
1378 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001379 else if (!strcmp(args[cur_arg], "if")) {
1380 pol = ACL_COND_IF;
1381 cur_arg++;
1382 break;
1383 }
1384 else if (!strcmp(args[cur_arg], "unless")) {
1385 pol = ACL_COND_UNLESS;
1386 cur_arg++;
1387 break;
1388 }
1389 else {
1390 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1391 file, linenum, args[0], args[cur_arg]);
1392 return -1;
1393 }
1394 cur_arg++;
1395 }
1396
1397 if (type == REDIRECT_TYPE_NONE) {
1398 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1399 file, linenum, args[0]);
1400 return -1;
1401 }
1402
1403 if (pol == ACL_COND_NONE) {
1404 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1405 file, linenum, args[0]);
1406 return -1;
1407 }
1408
1409 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001410 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001411 file, linenum, args[0]);
1412 return -1;
1413 }
1414
Willy Tarreaua9802632008-07-25 19:13:19 +02001415 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001416 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1417 rule->cond = cond;
1418 rule->rdr_str = strdup(destination);
1419 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001420 if (cookie) {
1421 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1422 * a clear consists in appending "; Max-Age=0" at the end.
1423 */
1424 rule->cookie_len = strlen(cookie);
1425 if (cookie_set)
1426 rule->cookie_str = strdup(cookie);
1427 else {
1428 rule->cookie_str = malloc(rule->cookie_len + 12);
1429 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1430 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1431 rule->cookie_len += 11;
1432 }
1433 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001434 rule->type = type;
1435 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001436 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001437 LIST_INIT(&rule->list);
1438 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001439 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001440 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001441 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001442 int pol = ACL_COND_NONE;
1443 struct acl_cond *cond;
1444 struct switching_rule *rule;
1445
Willy Tarreaub099aca2008-10-12 17:26:37 +02001446 if (curproxy == &defproxy) {
1447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1448 return -1;
1449 }
1450
Willy Tarreau55ea7572007-06-17 19:56:27 +02001451 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1452 return 0;
1453
1454 if (*(args[1]) == 0) {
1455 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1456 return -1;
1457 }
1458
1459 if (!strcmp(args[2], "if"))
1460 pol = ACL_COND_IF;
1461 else if (!strcmp(args[2], "unless"))
1462 pol = ACL_COND_UNLESS;
1463
1464 if (pol == ACL_COND_NONE) {
1465 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1466 file, linenum, args[0]);
1467 return -1;
1468 }
1469
1470 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001471 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001472 file, linenum);
1473 return -1;
1474 }
1475
Willy Tarreaua9802632008-07-25 19:13:19 +02001476 cond->line = linenum;
1477 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001478 struct acl *acl;
1479 const char *name;
1480
1481 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1482 name = acl ? acl->name : "(unknown)";
1483 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1484 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001485 }
1486
Willy Tarreau55ea7572007-06-17 19:56:27 +02001487 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1488 rule->cond = cond;
1489 rule->be.name = strdup(args[1]);
1490 LIST_INIT(&rule->list);
1491 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1495 return 0;
1496
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1498 curproxy->uri_auth = NULL; /* we must detach from the default config */
1499
1500 if (*(args[1]) == 0) {
1501 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1502 return -1;
1503 } else if (!strcmp(args[1], "uri")) {
1504 if (*(args[2]) == 0) {
1505 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1506 return -1;
1507 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1508 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1509 return -1;
1510 }
1511 } else if (!strcmp(args[1], "realm")) {
1512 if (*(args[2]) == 0) {
1513 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1514 return -1;
1515 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1517 return -1;
1518 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001519 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001520 unsigned interval;
1521
1522 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1523 if (err) {
1524 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1525 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001526 return -1;
1527 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1528 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1529 return -1;
1530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 } else if (!strcmp(args[1], "auth")) {
1532 if (*(args[2]) == 0) {
1533 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1534 return -1;
1535 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1536 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1537 return -1;
1538 }
1539 } else if (!strcmp(args[1], "scope")) {
1540 if (*(args[2]) == 0) {
1541 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1542 return -1;
1543 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1544 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1545 return -1;
1546 }
1547 } else if (!strcmp(args[1], "enable")) {
1548 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1549 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1550 return -1;
1551 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001552 } else if (!strcmp(args[1], "hide-version")) {
1553 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1554 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1555 return -1;
1556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001558 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 file, linenum, args[0]);
1560 return -1;
1561 }
1562 }
1563 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001564 int optnum;
1565
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001566 if (*(args[1]) == '\0') {
1567 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1568 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 return -1;
1570 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001571
1572 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1573 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1574 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1575 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001576
1577 if (!inv)
1578 curproxy->options |= cfg_opts[optnum].val;
1579 else
1580 curproxy->options &= ~cfg_opts[optnum].val;
1581
Willy Tarreau13943ab2006-12-31 00:24:10 +01001582 return 0;
1583 }
1584 }
1585
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001586 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1587 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1588 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1589 return 0;
1590
1591 if (!inv)
1592 curproxy->options2 |= cfg_opts2[optnum].val;
1593 else
1594 curproxy->options2 &= ~cfg_opts2[optnum].val;
1595
1596 return 0;
1597 }
1598 }
1599
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001600 if (inv) {
1601 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1602 file, linenum, args[1]);
1603 return -1;
1604 }
1605
Willy Tarreau13943ab2006-12-31 00:24:10 +01001606 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 /* generate a complete HTTP log */
1608 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1609 else if (!strcmp(args[1], "tcplog"))
1610 /* generate a detailed TCP log */
1611 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 else if (!strcmp(args[1], "tcpka")) {
1613 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001614 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1615 return 0;
1616
1617 if (curproxy->cap & PR_CAP_FE)
1618 curproxy->options |= PR_O_TCP_CLI_KA;
1619 if (curproxy->cap & PR_CAP_BE)
1620 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 }
1622 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1624 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001627 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001628 curproxy->options &= ~PR_O_SMTP_CHK;
1629 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 if (!*args[2]) { /* no argument */
1631 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1632 curproxy->check_len = strlen(DEF_CHECK_REQ);
1633 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001634 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 curproxy->check_req = (char *)malloc(reqlen);
1636 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1637 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1638 } else { /* more arguments : METHOD URI [HTTP_VER] */
1639 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1640 if (*args[4])
1641 reqlen += strlen(args[4]);
1642 else
1643 reqlen += strlen("HTTP/1.0");
1644
1645 curproxy->check_req = (char *)malloc(reqlen);
1646 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1647 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1648 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001649 }
1650 else if (!strcmp(args[1], "ssl-hello-chk")) {
1651 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001652 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1653 return 0;
1654
Willy Tarreaua534fea2008-08-03 12:19:50 +02001655 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001656 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001657 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001658 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
Willy Tarreau23677902007-05-08 23:50:35 +02001660 else if (!strcmp(args[1], "smtpchk")) {
1661 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001662 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001663 curproxy->options &= ~PR_O_HTTP_CHK;
1664 curproxy->options &= ~PR_O_SSL3_CHK;
1665 curproxy->options |= PR_O_SMTP_CHK;
1666
1667 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1668 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1669 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1670 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1671 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1672 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1673 curproxy->check_req = (char *)malloc(reqlen);
1674 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1675 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1676 } else {
1677 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1678 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1679 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1680 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1681 }
1682 }
1683 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001684 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001685 int cur_arg;
1686
1687 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1688 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001689 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001690
1691 curproxy->options |= PR_O_FWDFOR;
1692
1693 free(curproxy->fwdfor_hdr_name);
1694 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1695 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1696
1697 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1698 cur_arg = 2;
1699 while (*(args[cur_arg])) {
1700 if (!strcmp(args[cur_arg], "except")) {
1701 /* suboption except - needs additional argument for it */
1702 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1703 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1704 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001705 return -1;
1706 }
1707 /* flush useless bits */
1708 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001709 cur_arg += 2;
1710 } else if (!strcmp(args[cur_arg], "header")) {
1711 /* suboption header - needs additional argument for it */
1712 if (*(args[cur_arg+1]) == 0) {
1713 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1714 file, linenum, args[0], args[1], args[cur_arg]);
1715 return -1;
1716 }
1717 free(curproxy->fwdfor_hdr_name);
1718 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1719 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1720 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001721 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001722 /* unknown suboption - catchall */
1723 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1724 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001725 return -1;
1726 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001727 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001728 }
Maik Broemme2850cb42009-04-17 18:53:21 +02001729 else if (!strcmp(args[1], "originalto")) {
1730 int cur_arg;
1731
1732 /* insert x-original-to field, but not for the IP address listed as an except.
1733 * set default options (ie: bitfield, header name, etc)
1734 */
1735
1736 curproxy->options |= PR_O_ORGTO;
1737
1738 free(curproxy->orgto_hdr_name);
1739 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
1740 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
1741
1742 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1743 cur_arg = 2;
1744 while (*(args[cur_arg])) {
1745 if (!strcmp(args[cur_arg], "except")) {
1746 /* suboption except - needs additional argument for it */
1747 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
1748 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1749 file, linenum, args[0], args[1], args[cur_arg]);
1750 return -1;
1751 }
1752 /* flush useless bits */
1753 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
1754 cur_arg += 2;
1755 } else if (!strcmp(args[cur_arg], "header")) {
1756 /* suboption header - needs additional argument for it */
1757 if (*(args[cur_arg+1]) == 0) {
1758 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1759 file, linenum, args[0], args[1], args[cur_arg]);
1760 return -1;
1761 }
1762 free(curproxy->orgto_hdr_name);
1763 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
1764 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
1765 cur_arg += 2;
1766 } else {
1767 /* unknown suboption - catchall */
1768 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1769 file, linenum, args[0], args[1]);
1770 return -1;
1771 }
1772 } /* end while loop */
1773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 else {
1775 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1776 return -1;
1777 }
1778 return 0;
1779 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001780 else if (!strcmp(args[0], "default_backend")) {
1781 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1782 return 0;
1783
1784 if (*(args[1]) == 0) {
1785 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1786 return -1;
1787 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001788 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001789 curproxy->defbe.name = strdup(args[1]);
1790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1793 return 0;
1794
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001795 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1796 file, linenum, args[0]);
1797
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 /* enable reconnections to dispatch */
1799 curproxy->options |= PR_O_REDISP;
1800 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001801 else if (!strcmp(args[0], "http-check")) {
1802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1803 return 0;
1804
1805 if (strcmp(args[1], "disable-on-404") == 0) {
1806 /* enable a graceful server shutdown on an HTTP 404 response */
1807 curproxy->options |= PR_O_DISABLE404;
1808 }
1809 else {
1810 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1811 return -1;
1812 }
1813 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001814 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001815 if (curproxy == &defproxy) {
1816 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1817 return -1;
1818 }
1819
Willy Tarreaub80c2302007-11-30 20:51:32 +01001820 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1821 return 0;
1822
1823 if (strcmp(args[1], "fail") == 0) {
1824 /* add a condition to fail monitor requests */
1825 int pol = ACL_COND_NONE;
1826 struct acl_cond *cond;
1827
1828 if (!strcmp(args[2], "if"))
1829 pol = ACL_COND_IF;
1830 else if (!strcmp(args[2], "unless"))
1831 pol = ACL_COND_UNLESS;
1832
1833 if (pol == ACL_COND_NONE) {
1834 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1835 file, linenum, args[0], args[1]);
1836 return -1;
1837 }
1838
1839 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1840 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1841 file, linenum, args[0], args[1]);
1842 return -1;
1843 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001844 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001845 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1846 }
1847 else {
1848 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1849 return -1;
1850 }
1851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852#ifdef TPROXY
1853 else if (!strcmp(args[0], "transparent")) {
1854 /* enable transparent proxy connections */
1855 curproxy->options |= PR_O_TRANSP;
1856 }
1857#endif
1858 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001859 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1860 return 0;
1861
Willy Tarreaubaaee002006-06-26 02:48:02 +02001862 if (*(args[1]) == 0) {
1863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1864 return -1;
1865 }
1866 curproxy->maxconn = atol(args[1]);
1867 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001868 else if (!strcmp(args[0], "backlog")) { /* backlog */
1869 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1870 return 0;
1871
1872 if (*(args[1]) == 0) {
1873 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1874 return -1;
1875 }
1876 curproxy->backlog = atol(args[1]);
1877 }
Willy Tarreau86034312006-12-29 00:10:33 +01001878 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001879 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1880 return 0;
1881
Willy Tarreau86034312006-12-29 00:10:33 +01001882 if (*(args[1]) == 0) {
1883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1884 return -1;
1885 }
1886 curproxy->fullconn = atol(args[1]);
1887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1889 if (*(args[1]) == 0) {
1890 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1891 return -1;
1892 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001893 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1894 if (err) {
1895 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1896 file, linenum, *err);
1897 return -1;
1898 }
1899 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 }
1901 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1902 if (curproxy == &defproxy) {
1903 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1904 return -1;
1905 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1907 return 0;
1908
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 if (strchr(args[1], ':') == NULL) {
1910 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1911 return -1;
1912 }
1913 curproxy->dispatch_addr = *str2sa(args[1]);
1914 }
1915 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1917 return 0;
1918
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001919 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001920 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1921 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1922 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
1925 else if (!strcmp(args[0], "server")) { /* server address */
1926 int cur_arg;
1927 char *rport;
1928 char *raddr;
1929 short realport;
1930 int do_check;
1931
1932 if (curproxy == &defproxy) {
1933 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1934 return -1;
1935 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1937 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938
1939 if (!*args[2]) {
1940 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1941 file, linenum, args[0]);
1942 return -1;
1943 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001944
1945 err = invalid_char(args[1]);
1946 if (err) {
1947 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1948 file, linenum, *err, args[1]);
1949 return -1;
1950 }
1951
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1953 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1954 return -1;
1955 }
1956
1957 /* the servers are linked backwards first */
1958 newsrv->next = curproxy->srv;
1959 curproxy->srv = newsrv;
1960 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001961 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962
1963 LIST_INIT(&newsrv->pendconns);
1964 do_check = 0;
1965 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001966 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 newsrv->id = strdup(args[1]);
1968
1969 /* several ways to check the port component :
1970 * - IP => port=+0, relative
1971 * - IP: => port=+0, relative
1972 * - IP:N => port=N, absolute
1973 * - IP:+N => port=+N, relative
1974 * - IP:-N => port=-N, relative
1975 */
1976 raddr = strdup(args[2]);
1977 rport = strchr(raddr, ':');
1978 if (rport) {
1979 *rport++ = 0;
1980 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001981 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 newsrv->state |= SRV_MAPPORTS;
1983 } else {
1984 realport = 0;
1985 newsrv->state |= SRV_MAPPORTS;
1986 }
1987
1988 newsrv->addr = *str2sa(raddr);
1989 newsrv->addr.sin_port = htons(realport);
1990 free(raddr);
1991
1992 newsrv->curfd = -1; /* no health-check in progress */
1993 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001994 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1995 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 newsrv->rise = DEF_RISETIME;
1997 newsrv->fall = DEF_FALLTIME;
1998 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001999 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002000 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002001 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002002
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 cur_arg = 3;
2004 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002005 if (!strcmp(args[cur_arg], "id")) {
2006 struct server *target;
2007
2008 if (!*args[cur_arg + 1]) {
2009 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2010 file, linenum, args[cur_arg]);
2011 return -1;
2012 }
2013
2014 newsrv->puid = atol(args[cur_arg + 1]);
2015
2016 if (newsrv->puid< 1001) {
2017 Alert("parsing [%s:%d]: custom id has to be > 1000",
2018 file, linenum);
2019 return -1;
2020 }
2021
2022 for (target = proxy->srv; target; target = target->next)
2023 if (newsrv != target && newsrv->puid == target->puid) {
2024 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
2025 file, linenum, newsrv->id, target->id);
2026 return -1;
2027 }
2028 cur_arg += 2;
2029 }
2030 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 newsrv->cookie = strdup(args[cur_arg + 1]);
2032 newsrv->cklen = strlen(args[cur_arg + 1]);
2033 cur_arg += 2;
2034 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01002035 else if (!strcmp(args[cur_arg], "redir")) {
2036 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
2037 newsrv->rdr_len = strlen(args[cur_arg + 1]);
2038 cur_arg += 2;
2039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 else if (!strcmp(args[cur_arg], "rise")) {
2041 newsrv->rise = atol(args[cur_arg + 1]);
2042 newsrv->health = newsrv->rise;
2043 cur_arg += 2;
2044 }
2045 else if (!strcmp(args[cur_arg], "fall")) {
2046 newsrv->fall = atol(args[cur_arg + 1]);
2047 cur_arg += 2;
2048 }
2049 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002050 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2051 if (err) {
2052 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2053 file, linenum, *err, newsrv->id);
2054 return -1;
2055 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002056 if (val <= 0) {
2057 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2058 file, linenum, val, args[cur_arg], newsrv->id);
2059 return -1;
2060 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002061 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 cur_arg += 2;
2063 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002064 else if (!strcmp(args[cur_arg], "fastinter")) {
2065 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2066 if (err) {
2067 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2068 file, linenum, *err, newsrv->id);
2069 return -1;
2070 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002071 if (val <= 0) {
2072 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2073 file, linenum, val, args[cur_arg], newsrv->id);
2074 return -1;
2075 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002076 newsrv->fastinter = val;
2077 cur_arg += 2;
2078 }
2079 else if (!strcmp(args[cur_arg], "downinter")) {
2080 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2081 if (err) {
2082 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2083 file, linenum, *err, newsrv->id);
2084 return -1;
2085 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002086 if (val <= 0) {
2087 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2088 file, linenum, val, args[cur_arg], newsrv->id);
2089 return -1;
2090 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002091 newsrv->downinter = val;
2092 cur_arg += 2;
2093 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002094 else if (!strcmp(args[cur_arg], "addr")) {
2095 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002096 cur_arg += 2;
2097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 else if (!strcmp(args[cur_arg], "port")) {
2099 newsrv->check_port = atol(args[cur_arg + 1]);
2100 cur_arg += 2;
2101 }
2102 else if (!strcmp(args[cur_arg], "backup")) {
2103 newsrv->state |= SRV_BACKUP;
2104 cur_arg ++;
2105 }
2106 else if (!strcmp(args[cur_arg], "weight")) {
2107 int w;
2108 w = atol(args[cur_arg + 1]);
2109 if (w < 1 || w > 256) {
2110 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
2111 file, linenum, newsrv->id, w);
2112 return -1;
2113 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002114 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 cur_arg += 2;
2116 }
2117 else if (!strcmp(args[cur_arg], "minconn")) {
2118 newsrv->minconn = atol(args[cur_arg + 1]);
2119 cur_arg += 2;
2120 }
2121 else if (!strcmp(args[cur_arg], "maxconn")) {
2122 newsrv->maxconn = atol(args[cur_arg + 1]);
2123 cur_arg += 2;
2124 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002125 else if (!strcmp(args[cur_arg], "maxqueue")) {
2126 newsrv->maxqueue = atol(args[cur_arg + 1]);
2127 cur_arg += 2;
2128 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002129 else if (!strcmp(args[cur_arg], "slowstart")) {
2130 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002131 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002132 if (err) {
2133 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2134 file, linenum, *err, newsrv->id);
2135 return -1;
2136 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002137 if (val <= 0) {
2138 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2139 file, linenum, val, args[cur_arg], newsrv->id);
2140 return -1;
2141 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002142 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002143 cur_arg += 2;
2144 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002145 else if (!strcmp(args[cur_arg], "track")) {
2146
2147 if (!*args[cur_arg + 1]) {
2148 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2149 file, linenum);
2150 return -1;
2151 }
2152
2153 newsrv->trackit = strdup(args[cur_arg + 1]);
2154
2155 cur_arg += 2;
2156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 else if (!strcmp(args[cur_arg], "check")) {
2158 global.maxsock++;
2159 do_check = 1;
2160 cur_arg += 1;
2161 }
2162 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2163 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002164#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002165 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2166 file, linenum, "source", "usesrc");
2167#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2169 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002170#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 return -1;
2172 }
2173 newsrv->state |= SRV_BIND_SRC;
2174 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2175 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002176 while (*(args[cur_arg])) {
2177 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002178#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2179#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002180 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2181 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2182 file, linenum, "usesrc", "source");
2183 return -1;
2184 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002185#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002186 if (!*args[cur_arg + 1]) {
2187 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2188 file, linenum, "usesrc");
2189 return -1;
2190 }
2191 if (!strcmp(args[cur_arg + 1], "client")) {
2192 newsrv->state |= SRV_TPROXY_CLI;
2193 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2194 newsrv->state |= SRV_TPROXY_CIP;
2195 } else {
2196 newsrv->state |= SRV_TPROXY_ADDR;
2197 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2198 }
2199 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002200#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002201 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002202#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002203 cur_arg += 2;
2204 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002205#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002206 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002207 file, linenum, "usesrc");
2208 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002209#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2210 } /* "usesrc" */
2211
2212 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2213#ifdef SO_BINDTODEVICE
2214 if (!*args[cur_arg + 1]) {
2215 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2216 file, linenum, args[0]);
2217 return -1;
2218 }
2219 if (newsrv->iface_name)
2220 free(newsrv->iface_name);
2221
2222 newsrv->iface_name = strdup(args[cur_arg + 1]);
2223 newsrv->iface_len = strlen(newsrv->iface_name);
2224 global.last_checks |= LSTCHK_NETADM;
2225#else
2226 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2227 file, linenum, args[0], args[cur_arg]);
2228 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002229#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002230 cur_arg += 2;
2231 continue;
2232 }
2233 /* this keyword in not an option of "source" */
2234 break;
2235 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002237 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2238 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2239 file, linenum, "usesrc", "source");
2240 return -1;
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 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 +02002244 file, linenum, newsrv->id);
2245 return -1;
2246 }
2247 }
2248
2249 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002250 if (newsrv->trackit) {
2251 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2252 file, linenum);
2253 return -1;
2254 }
2255
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002256 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2257 newsrv->check_port = newsrv->check_addr.sin_port;
2258
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2260 newsrv->check_port = realport; /* by default */
2261 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002262 /* not yet valid, because no port was set on
2263 * the server either. We'll check if we have
2264 * a known port on the first listener.
2265 */
2266 struct listener *l;
2267 l = curproxy->listen;
2268 if (l) {
2269 int port;
2270 port = (l->addr.ss_family == AF_INET6)
2271 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2272 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2273 newsrv->check_port = port;
2274 }
2275 }
2276 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2278 file, linenum, newsrv->id);
2279 return -1;
2280 }
2281 newsrv->state |= SRV_CHECKED;
2282 }
2283
2284 if (newsrv->state & SRV_BACKUP)
2285 curproxy->srv_bck++;
2286 else
2287 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002288
2289 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 }
2291 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002292 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293 int facility;
2294
2295 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2296 curproxy->logfac1 = global.logfac1;
2297 curproxy->logsrv1 = global.logsrv1;
2298 curproxy->loglev1 = global.loglev1;
2299 curproxy->logfac2 = global.logfac2;
2300 curproxy->logsrv2 = global.logsrv2;
2301 curproxy->loglev2 = global.loglev2;
2302 }
2303 else if (*(args[1]) && *(args[2])) {
2304 int level;
2305
2306 facility = get_log_facility(args[2]);
2307 if (facility < 0) {
2308 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2309 exit(1);
2310 }
2311
2312 level = 7; /* max syslog level = debug */
2313 if (*(args[3])) {
2314 level = get_log_level(args[3]);
2315 if (level < 0) {
2316 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2317 exit(1);
2318 }
2319 }
2320
Robert Tsai81ae1952007-12-05 10:47:29 +01002321 if (args[1][0] == '/') {
2322 logsrv.u.addr.sa_family = AF_UNIX;
2323 logsrv.u.un = *str2sun(args[1]);
2324 } else {
2325 logsrv.u.addr.sa_family = AF_INET;
2326 logsrv.u.in = *str2sa(args[1]);
2327 if (!logsrv.u.in.sin_port) {
2328 logsrv.u.in.sin_port =
2329 htons(SYSLOG_PORT);
2330 }
2331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332
2333 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002334 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 curproxy->logfac1 = facility;
2336 curproxy->loglev1 = level;
2337 }
2338 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002339 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 curproxy->logfac2 = facility;
2341 curproxy->loglev2 = level;
2342 }
2343 else {
2344 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2345 return -1;
2346 }
2347 }
2348 else {
2349 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2350 file, linenum);
2351 return -1;
2352 }
2353 }
2354 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002355 int cur_arg;
2356
Willy Tarreau977b8e42006-12-29 14:19:17 +01002357 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2358 return 0;
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002361 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2362 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 return -1;
2364 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002365
2366 /* we must first clear any optional default setting */
2367 curproxy->options &= ~PR_O_TPXY_MASK;
2368 free(curproxy->iface_name);
2369 curproxy->iface_name = NULL;
2370 curproxy->iface_len = 0;
2371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 curproxy->source_addr = *str2sa(args[1]);
2373 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002374
2375 cur_arg = 2;
2376 while (*(args[cur_arg])) {
2377 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002378#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2379#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002380 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2381 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2382 file, linenum, "usesrc");
2383 return -1;
2384 }
2385#endif
2386 if (!*args[cur_arg + 1]) {
2387 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2388 file, linenum, "usesrc");
2389 return -1;
2390 }
2391
2392 if (!strcmp(args[cur_arg + 1], "client")) {
2393 curproxy->options |= PR_O_TPXY_CLI;
2394 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2395 curproxy->options |= PR_O_TPXY_CIP;
2396 } else {
2397 curproxy->options |= PR_O_TPXY_ADDR;
2398 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2399 }
2400 global.last_checks |= LSTCHK_NETADM;
2401#if !defined(CONFIG_HAP_LINUX_TPROXY)
2402 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002403#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002404#else /* no TPROXY support */
2405 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002406 file, linenum, "usesrc");
2407 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002408#endif
2409 cur_arg += 2;
2410 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002411 }
2412
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002413 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2414#ifdef SO_BINDTODEVICE
2415 if (!*args[cur_arg + 1]) {
2416 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2417 file, linenum, args[0]);
2418 return -1;
2419 }
2420 if (curproxy->iface_name)
2421 free(curproxy->iface_name);
2422
2423 curproxy->iface_name = strdup(args[cur_arg + 1]);
2424 curproxy->iface_len = strlen(curproxy->iface_name);
2425 global.last_checks |= LSTCHK_NETADM;
2426#else
2427 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2428 file, linenum, args[0], args[cur_arg]);
2429 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002430#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002431 cur_arg += 2;
2432 continue;
2433 }
2434 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2435 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002436 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002439 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2440 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2441 file, linenum, "usesrc", "source");
2442 return -1;
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2445 regex_t *preg;
2446 if (curproxy == &defproxy) {
2447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2448 return -1;
2449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2451 return 0;
2452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (*(args[1]) == 0 || *(args[2]) == 0) {
2454 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2455 file, linenum, args[0]);
2456 return -1;
2457 }
2458
2459 preg = calloc(1, sizeof(regex_t));
2460 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2461 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2462 return -1;
2463 }
2464
2465 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2466 if (err) {
2467 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2468 file, linenum, *err);
2469 return -1;
2470 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002471 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }
2473 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2474 regex_t *preg;
2475 if (curproxy == &defproxy) {
2476 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2477 return -1;
2478 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002479 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2480 return 0;
2481
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 if (*(args[1]) == 0) {
2483 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2484 return -1;
2485 }
2486
2487 preg = calloc(1, sizeof(regex_t));
2488 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2489 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2490 return -1;
2491 }
2492
2493 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002494 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
2496 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2497 regex_t *preg;
2498 if (curproxy == &defproxy) {
2499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2500 return -1;
2501 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002502 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2503 return 0;
2504
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 if (*(args[1]) == 0) {
2506 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2507 return -1;
2508 }
2509
2510 preg = calloc(1, sizeof(regex_t));
2511 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2512 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2513 return -1;
2514 }
2515
2516 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002517 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 }
2519 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2520 regex_t *preg;
2521 if (curproxy == &defproxy) {
2522 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2523 return -1;
2524 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002525 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2526 return 0;
2527
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 if (*(args[1]) == 0) {
2529 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2530 return -1;
2531 }
2532
2533 preg = calloc(1, sizeof(regex_t));
2534 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2535 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2536 return -1;
2537 }
2538
2539 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002540 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 }
2542 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2543 regex_t *preg;
2544 if (curproxy == &defproxy) {
2545 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2546 return -1;
2547 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2549 return 0;
2550
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 if (*(args[1]) == 0) {
2552 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2553 return -1;
2554 }
2555
2556 preg = calloc(1, sizeof(regex_t));
2557 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2558 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2559 return -1;
2560 }
2561
2562 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002563 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002565 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2566 regex_t *preg;
2567 if (curproxy == &defproxy) {
2568 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2569 return -1;
2570 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2572 return 0;
2573
Willy Tarreaub8750a82006-09-03 09:56:00 +02002574 if (*(args[1]) == 0) {
2575 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2576 return -1;
2577 }
2578
2579 preg = calloc(1, sizeof(regex_t));
2580 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2581 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2582 return -1;
2583 }
2584
2585 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002586 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002587 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002588 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2589 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002590 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002591 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2592 return -1;
2593 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002594 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2595 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002596
Willy Tarreau977b8e42006-12-29 14:19:17 +01002597 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002598 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2599 file, linenum, args[0]);
2600 return -1;
2601 }
2602
2603 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002605 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2606 }
2607
2608 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002609 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002610 }
2611 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2612 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2615 return -1;
2616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002617 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2618 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002619
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002621 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2622 file, linenum, args[0]);
2623 return -1;
2624 }
2625
2626 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002627 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002628 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2629 }
2630
2631 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002632 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2635 regex_t *preg;
2636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2638 return -1;
2639 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002640 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2641 return 0;
2642
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 if (*(args[1]) == 0 || *(args[2]) == 0) {
2644 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2645 file, linenum, args[0]);
2646 return -1;
2647 }
2648
2649 preg = calloc(1, sizeof(regex_t));
2650 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2651 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2652 return -1;
2653 }
2654
2655 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2656 if (err) {
2657 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2658 file, linenum, *err);
2659 return -1;
2660 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002661 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
2663 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2664 regex_t *preg;
2665 if (curproxy == &defproxy) {
2666 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2667 return -1;
2668 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2670 return 0;
2671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (*(args[1]) == 0) {
2673 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2674 return -1;
2675 }
2676
2677 preg = calloc(1, sizeof(regex_t));
2678 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2679 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2680 return -1;
2681 }
2682
2683 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002684 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
2686 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2687 regex_t *preg;
2688 if (curproxy == &defproxy) {
2689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2690 return -1;
2691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2693 return 0;
2694
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 if (*(args[1]) == 0) {
2696 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2697 return -1;
2698 }
2699
2700 preg = calloc(1, sizeof(regex_t));
2701 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2702 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2703 return -1;
2704 }
2705
2706 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002707 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 }
2709 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2710 regex_t *preg;
2711 if (curproxy == &defproxy) {
2712 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2713 return -1;
2714 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002715 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2716 return 0;
2717
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 if (*(args[1]) == 0) {
2719 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2720 return -1;
2721 }
2722
2723 preg = calloc(1, sizeof(regex_t));
2724 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2725 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2726 return -1;
2727 }
2728
2729 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002730 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
2732 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2733 regex_t *preg;
2734 if (curproxy == &defproxy) {
2735 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2736 return -1;
2737 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002738 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2739 return 0;
2740
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741 if (*(args[1]) == 0) {
2742 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2743 return -1;
2744 }
2745
2746 preg = calloc(1, sizeof(regex_t));
2747 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2748 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2749 return -1;
2750 }
2751
2752 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002753 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002755 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2756 regex_t *preg;
2757 if (curproxy == &defproxy) {
2758 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2759 return -1;
2760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002761 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2762 return 0;
2763
Willy Tarreaub8750a82006-09-03 09:56:00 +02002764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2766 return -1;
2767 }
2768
2769 preg = calloc(1, sizeof(regex_t));
2770 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2771 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2772 return -1;
2773 }
2774
2775 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002776 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002777 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2779 if (curproxy == &defproxy) {
2780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2781 return -1;
2782 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2784 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785
2786 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2787 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2788 return 0;
2789 }
2790
2791 if (*(args[1]) == 0) {
2792 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2793 return -1;
2794 }
2795
2796 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002797 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
2799 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2800 regex_t *preg;
2801
2802 if (*(args[1]) == 0 || *(args[2]) == 0) {
2803 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2804 file, linenum, args[0]);
2805 return -1;
2806 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2808 return 0;
2809
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 preg = calloc(1, sizeof(regex_t));
2811 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2812 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2813 return -1;
2814 }
2815
2816 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2817 if (err) {
2818 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2819 file, linenum, *err);
2820 return -1;
2821 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002822 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002823 }
2824 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2825 regex_t *preg;
2826 if (curproxy == &defproxy) {
2827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2828 return -1;
2829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002830 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2831 return 0;
2832
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 if (*(args[1]) == 0) {
2834 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2835 return -1;
2836 }
2837
2838 preg = calloc(1, sizeof(regex_t));
2839 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2840 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2841 return -1;
2842 }
2843
2844 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2845 if (err) {
2846 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2847 file, linenum, *err);
2848 return -1;
2849 }
2850 }
2851 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2852 regex_t *preg;
2853 if (curproxy == &defproxy) {
2854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2855 return -1;
2856 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002857 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2858 return 0;
2859
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 if (*(args[1]) == 0) {
2861 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2862 return -1;
2863 }
2864
2865 preg = calloc(1, sizeof(regex_t));
2866 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2867 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2868 return -1;
2869 }
2870
2871 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2872 if (err) {
2873 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2874 file, linenum, *err);
2875 return -1;
2876 }
2877 }
2878 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2879 regex_t *preg;
2880 if (curproxy == &defproxy) {
2881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2882 return -1;
2883 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002884 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2885 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886
2887 if (*(args[1]) == 0 || *(args[2]) == 0) {
2888 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2889 file, linenum, args[0]);
2890 return -1;
2891 }
2892
2893 preg = calloc(1, sizeof(regex_t));
2894 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2895 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2896 return -1;
2897 }
2898
2899 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2900 if (err) {
2901 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2902 file, linenum, *err);
2903 return -1;
2904 }
2905 }
2906 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2907 regex_t *preg;
2908 if (curproxy == &defproxy) {
2909 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2910 return -1;
2911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2913 return 0;
2914
Willy Tarreaubaaee002006-06-26 02:48:02 +02002915 if (*(args[1]) == 0) {
2916 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2917 return -1;
2918 }
2919
2920 preg = calloc(1, sizeof(regex_t));
2921 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2922 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2923 return -1;
2924 }
2925
2926 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2927 if (err) {
2928 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2929 file, linenum, *err);
2930 return -1;
2931 }
2932 }
2933 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2934 regex_t *preg;
2935 if (curproxy == &defproxy) {
2936 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2937 return -1;
2938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002939 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2940 return 0;
2941
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 if (*(args[1]) == 0) {
2943 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2944 return -1;
2945 }
2946
2947 preg = calloc(1, sizeof(regex_t));
2948 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2949 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2950 return -1;
2951 }
2952
2953 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2954 if (err) {
2955 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2956 file, linenum, *err);
2957 return -1;
2958 }
2959 }
2960 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2963 return -1;
2964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2966 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967
2968 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2969 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2970 return 0;
2971 }
2972
2973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2975 return -1;
2976 }
2977
2978 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2979 }
2980 else if (!strcmp(args[0], "errorloc") ||
2981 !strcmp(args[0], "errorloc302") ||
2982 !strcmp(args[0], "errorloc303")) { /* error location */
2983 int errnum, errlen;
2984 char *err;
2985
Willy Tarreau977b8e42006-12-29 14:19:17 +01002986 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2987 return 0;
2988
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02002990 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 return -1;
2992 }
2993
2994 errnum = atol(args[1]);
2995 if (!strcmp(args[0], "errorloc303")) {
2996 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2997 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2998 } else {
2999 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
3000 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
3001 }
3002
Willy Tarreau0f772532006-12-23 20:51:41 +01003003 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3004 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003005 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01003006 curproxy->errmsg[rc].str = err;
3007 curproxy->errmsg[rc].len = errlen;
3008 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003011
3012 if (rc >= HTTP_ERR_SIZE) {
3013 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
3014 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 free(err);
3016 }
3017 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02003018 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
3019 int errnum, errlen, fd;
3020 char *err;
3021 struct stat stat;
3022
3023 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
3024 return 0;
3025
3026 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003027 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003028 return -1;
3029 }
3030
3031 fd = open(args[2], O_RDONLY);
3032 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
3033 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
3034 file, linenum, args[2], args[1]);
3035 if (fd >= 0)
3036 close(fd);
3037 return -1;
3038 }
3039
3040 if (stat.st_size <= BUFSIZE) {
3041 errlen = stat.st_size;
3042 } else {
3043 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
3044 file, linenum, args[2], BUFSIZE);
3045 errlen = BUFSIZE;
3046 }
3047
3048 err = malloc(errlen); /* malloc() must succeed during parsing */
3049 errnum = read(fd, err, errlen);
3050 if (errnum != errlen) {
3051 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3052 file, linenum, args[2], args[1]);
3053 close(fd);
3054 free(err);
3055 return -1;
3056 }
3057 close(fd);
3058
3059 errnum = atol(args[1]);
3060 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3061 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003062 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003063 curproxy->errmsg[rc].str = err;
3064 curproxy->errmsg[rc].len = errlen;
3065 break;
3066 }
3067 }
3068
3069 if (rc >= HTTP_ERR_SIZE) {
3070 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3071 file, linenum, errnum);
3072 free(err);
3073 }
3074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003076 struct cfg_kw_list *kwl;
3077 int index;
3078
3079 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3080 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3081 if (kwl->kw[index].section != CFG_LISTEN)
3082 continue;
3083 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3084 /* prepare error message just in case */
3085 snprintf(trash, sizeof(trash),
3086 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003087 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3088 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003089 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3090 return -1;
3091 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003092 else if (rc > 0) {
3093 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3094 return 0;
3095 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003096 return 0;
3097 }
3098 }
3099 }
3100
Willy Tarreau6daf3432008-01-22 16:44:08 +01003101 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 return -1;
3103 }
3104 return 0;
3105}
3106
3107
3108/*
3109 * This function reads and parses the configuration file given in the argument.
3110 * returns 0 if OK, -1 if error.
3111 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003112int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003114 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 FILE *f;
3116 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 int confsect = CFG_NONE;
3119
3120 struct proxy *curproxy = NULL;
3121 struct server *newsrv = NULL;
3122
3123 if ((f=fopen(file,"r")) == NULL)
3124 return -1;
3125
3126 init_default_instance();
3127
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003128 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003129 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003130 char *end;
3131 char *args[MAX_LINE_ARGS + 1];
3132 char *line = thisline;
3133
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 linenum++;
3135
3136 end = line + strlen(line);
3137
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003138 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3139 /* Check if we reached the limit and the last char is not \n.
3140 * Watch out for the last line without the terminating '\n'!
3141 */
3142 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02003143 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003144 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003145 }
3146
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003148 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 line++;
3150
3151 arg = 0;
3152 args[arg] = line;
3153
3154 while (*line && arg < MAX_LINE_ARGS) {
3155 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3156 * C equivalent value. Other combinations left unchanged (eg: \1).
3157 */
3158 if (*line == '\\') {
3159 int skip = 0;
3160 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3161 *line = line[1];
3162 skip = 1;
3163 }
3164 else if (line[1] == 'r') {
3165 *line = '\r';
3166 skip = 1;
3167 }
3168 else if (line[1] == 'n') {
3169 *line = '\n';
3170 skip = 1;
3171 }
3172 else if (line[1] == 't') {
3173 *line = '\t';
3174 skip = 1;
3175 }
3176 else if (line[1] == 'x') {
3177 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3178 unsigned char hex1, hex2;
3179 hex1 = toupper(line[2]) - '0';
3180 hex2 = toupper(line[3]) - '0';
3181 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3182 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3183 *line = (hex1<<4) + hex2;
3184 skip = 3;
3185 }
3186 else {
3187 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003188 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
3190 }
3191 if (skip) {
3192 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3193 end -= skip;
3194 }
3195 line++;
3196 }
3197 else if (*line == '#' || *line == '\n' || *line == '\r') {
3198 /* end of string, end of loop */
3199 *line = 0;
3200 break;
3201 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003202 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003204 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003205 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 line++;
3207 args[++arg] = line;
3208 }
3209 else {
3210 line++;
3211 }
3212 }
3213
3214 /* empty line */
3215 if (!**args)
3216 continue;
3217
Willy Tarreau540abe42007-05-02 20:50:16 +02003218 /* zero out remaining args and ensure that at least one entry
3219 * is zeroed out.
3220 */
3221 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 args[arg] = line;
3223 }
3224
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003225 if (!strcmp(args[0], "no")) {
3226 inv = 1;
3227 for (arg=0; *args[arg+1]; arg++)
3228 args[arg] = args[arg+1]; // shift args after inversion
3229 }
3230
3231 if (inv && strcmp(args[0], "option")) {
3232 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003233 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003234 }
3235
Willy Tarreau977b8e42006-12-29 14:19:17 +01003236 if (!strcmp(args[0], "listen") ||
3237 !strcmp(args[0], "frontend") ||
3238 !strcmp(args[0], "backend") ||
3239 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003240 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003242 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003243 cursection = strdup(args[0]);
3244 }
3245 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003247 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003248 cursection = strdup(args[0]);
3249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 /* else it's a section keyword */
3251
3252 switch (confsect) {
3253 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003254 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003255 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 break;
3257 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003258 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003259 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 break;
3261 default:
3262 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003263 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003266 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003267 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 fclose(f);
3269
3270 /*
3271 * Now, check for the integrity of all that we have collected.
3272 */
3273
3274 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003275 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003277 /* first, we will invert the proxy list order */
3278 curproxy = NULL;
3279 while (proxy) {
3280 struct proxy *next;
3281
3282 next = proxy->next;
3283 proxy->next = curproxy;
3284 curproxy = proxy;
3285 if (!next)
3286 break;
3287 proxy = next;
3288 }
3289
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 if ((curproxy = proxy) == NULL) {
3291 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3292 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003293 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
3295
3296 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003297 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003298 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003299
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003301 /* ensure we don't keep listeners uselessly bound */
3302 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 curproxy = curproxy->next;
3304 continue;
3305 }
3306
Willy Tarreauff01a212009-03-15 13:46:16 +01003307 switch (curproxy->mode) {
3308 case PR_MODE_HEALTH:
3309 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3310 if (!(curproxy->cap & PR_CAP_FE)) {
3311 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3312 file, proxy_type_str(curproxy), curproxy->id);
3313 cfgerr++;
3314 }
3315
3316 if (curproxy->srv != NULL)
3317 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3318 file, proxy_type_str(curproxy), curproxy->id);
3319 break;
3320
3321 case PR_MODE_TCP:
3322 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3323 break;
3324
3325 case PR_MODE_HTTP:
3326 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3327 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3328 file, curproxy->id);
3329 cfgerr++;
3330 }
3331 break;
3332 }
3333
3334 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003335 Alert("parsing %s : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003336 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 cfgerr++;
3338 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003339
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003340 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3341 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3342 if (curproxy->options & PR_O_TRANSP) {
3343 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3344 file, proxy_type_str(curproxy), curproxy->id);
3345 cfgerr++;
3346 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003348 else if (curproxy->srv == NULL) {
3349 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3350 file, proxy_type_str(curproxy), curproxy->id);
3351 cfgerr++;
3352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003354 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3355 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3356 file, proxy_type_str(curproxy), curproxy->id);
3357 }
3358 }
3359 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3360 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3361 /* If no LB algo is set in a backend, and we're not in
3362 * transparent mode, dispatch mode nor proxy mode, we
3363 * want to use balance roundrobin by default.
3364 */
3365 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3366 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
3368 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003369
Willy Tarreau82936582007-11-30 15:20:09 +01003370 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3371 curproxy->options &= ~PR_O_DISABLE404;
3372 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3373 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3374 }
3375
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003376 /* if a default backend was specified, let's find it */
3377 if (curproxy->defbe.name) {
3378 struct proxy *target;
3379
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003380 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3381 if (!target) {
3382 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3383 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003384 cfgerr++;
3385 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003386 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3387 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003388 } else {
3389 free(curproxy->defbe.name);
3390 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003391 /* we force the backend to be present on at least all of
3392 * the frontend's processes.
3393 */
3394 target->bind_proc = curproxy->bind_proc ?
3395 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397 }
3398
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003399 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003400 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3401 /* map jump target for ACT_SETBE in req_rep chain */
3402 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003403 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003404 struct proxy *target;
3405
Willy Tarreaua496b602006-12-17 23:15:24 +01003406 if (exp->action != ACT_SETBE)
3407 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003408
3409 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3410 if (!target) {
3411 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3412 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003413 cfgerr++;
3414 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003415 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3416 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003417 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003418 } else {
3419 free((void *)exp->replace);
3420 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003421 /* we force the backend to be present on at least all of
3422 * the frontend's processes.
3423 */
3424 target->bind_proc = curproxy->bind_proc ?
3425 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003426 }
3427 }
3428 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003429
3430 /* find the target proxy for 'use_backend' rules */
3431 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003432 struct proxy *target;
3433
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003434 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003435
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003436 if (!target) {
3437 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3438 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003439 cfgerr++;
3440 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003441 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3442 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003443 cfgerr++;
3444 } else {
3445 free((void *)rule->be.name);
3446 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003447 /* we force the backend to be present on at least all of
3448 * the frontend's processes.
3449 */
3450 target->bind_proc = curproxy->bind_proc ?
3451 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003452 }
3453 }
3454
Willy Tarreau2738a142006-07-08 17:28:09 +02003455 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003456 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003457 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003458 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003459 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003460 " | While not properly invalid, you will certainly encounter various problems\n"
3461 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003462 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003463 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003464 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003465
Willy Tarreau1fa31262007-12-03 00:36:16 +01003466 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3467 * We must still support older configurations, so let's find out whether those
3468 * parameters have been set or must be copied from contimeouts.
3469 */
3470 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003471 if (!curproxy->timeout.tarpit ||
3472 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003473 /* tarpit timeout not set. We search in the following order:
3474 * default.tarpit, curr.connect, default.connect.
3475 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003476 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003477 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003478 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003479 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003480 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003481 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003482 }
3483 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003484 (!curproxy->timeout.queue ||
3485 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003486 /* queue timeout not set. We search in the following order:
3487 * default.queue, curr.connect, default.connect.
3488 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003489 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003490 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003491 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003492 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003493 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003494 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003495 }
3496 }
3497
Willy Tarreauf3c69202006-07-09 16:42:34 +02003498 if (curproxy->options & PR_O_SSL3_CHK) {
3499 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3500 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3501 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3502 }
3503
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003504 /* The small pools required for the capture lists */
3505 if (curproxy->nb_req_cap)
3506 curproxy->req_cap_pool = create_pool("ptrcap",
3507 curproxy->nb_req_cap * sizeof(char *),
3508 MEM_F_SHARED);
3509 if (curproxy->nb_rsp_cap)
3510 curproxy->rsp_cap_pool = create_pool("ptrcap",
3511 curproxy->nb_rsp_cap * sizeof(char *),
3512 MEM_F_SHARED);
3513
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003514 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3515 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3516 MEM_F_SHARED);
3517
Willy Tarreau86034312006-12-29 00:10:33 +01003518 /* for backwards compatibility with "listen" instances, if
3519 * fullconn is not set but maxconn is set, then maxconn
3520 * is used.
3521 */
3522 if (!curproxy->fullconn)
3523 curproxy->fullconn = curproxy->maxconn;
3524
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 /* first, we will invert the servers list order */
3526 newsrv = NULL;
3527 while (curproxy->srv) {
3528 struct server *next;
3529
3530 next = curproxy->srv->next;
3531 curproxy->srv->next = newsrv;
3532 newsrv = curproxy->srv;
3533 if (!next)
3534 break;
3535 curproxy->srv = next;
3536 }
3537
Willy Tarreau20697042007-11-15 23:26:18 +01003538 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003539 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540
Willy Tarreaub625a082007-11-26 01:15:43 +01003541 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003542 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003543 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003544 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3545 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003546 else
3547 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548
3549 if (curproxy->options & PR_O_LOGASAP)
3550 curproxy->to_log &= ~LW_BYTES;
3551
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003553 * ensure that we're not cross-dressing a TCP server into HTTP.
3554 */
3555 newsrv = curproxy->srv;
3556 while (newsrv != NULL) {
3557 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003558 Alert("parsing [%s:%d] : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3559 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003560 goto err;
3561 }
3562 newsrv = newsrv->next;
3563 }
3564
3565 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 * If this server supports a maxconn parameter, it needs a dedicated
3567 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003568 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 */
3570 newsrv = curproxy->srv;
3571 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003572 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003573 /* Only 'minconn' was specified, or it was higher than or equal
3574 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3575 * this will avoid further useless expensive computations.
3576 */
3577 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003578 } else if (newsrv->maxconn && !newsrv->minconn) {
3579 /* minconn was not specified, so we set it to maxconn */
3580 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003581 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003582 Alert("parsing [%s:%d] : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3583 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003584 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 }
3586
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003587 if (newsrv->trackit) {
3588 struct proxy *px;
3589 struct server *srv;
3590 char *pname, *sname;
3591
3592 pname = newsrv->trackit;
3593 sname = strrchr(pname, '/');
3594
3595 if (sname)
3596 *sname++ = '\0';
3597 else {
3598 sname = pname;
3599 pname = NULL;
3600 }
3601
3602 if (pname) {
3603 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3604 if (!px) {
3605 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3606 file, proxy_type_str(curproxy), curproxy->id,
3607 newsrv->id, pname);
3608 return -1;
3609 }
3610 } else
3611 px = curproxy;
3612
3613 srv = findserver(px, sname);
3614 if (!srv) {
3615 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3616 file, proxy_type_str(curproxy), curproxy->id,
3617 newsrv->id, sname);
3618 return -1;
3619 }
3620
3621 if (!(srv->state & SRV_CHECKED)) {
3622 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3623 "tracing as it does not have checks enabled.\n",
3624 file, proxy_type_str(curproxy), curproxy->id,
3625 newsrv->id, px->id, srv->id);
3626 return -1;
3627 }
3628
3629 if (curproxy != px &&
3630 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3631 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3632 "tracing: disable-on-404 option inconsistency.\n",
3633 file, proxy_type_str(curproxy), curproxy->id,
3634 newsrv->id, px->id, srv->id);
3635 return -1;
3636 }
3637
3638 newsrv->tracked = srv;
3639 newsrv->tracknext = srv->tracknext;
3640 srv->tracknext = newsrv;
3641
3642 free(newsrv->trackit);
3643 }
3644
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 newsrv = newsrv->next;
3646 }
3647
Willy Tarreaue6b98942007-10-29 01:09:36 +01003648 /* adjust this proxy's listeners */
3649 listener = curproxy->listen;
3650 while (listener) {
3651 if (curproxy->options & PR_O_TCP_NOLING)
3652 listener->options |= LI_O_NOLINGER;
3653 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003654 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003655 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003656 listener->accept = event_accept;
3657 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003658 listener->handler = process_session;
3659
3660 if (curproxy->mode == PR_MODE_HTTP)
3661 listener->analysers |= AN_REQ_HTTP_HDR;
3662
Willy Tarreaud869b242009-03-15 14:43:58 +01003663 if (curproxy->tcp_req.inspect_delay ||
3664 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003665 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003666
3667 listener = listener->next;
3668 }
3669
Willy Tarreaubaaee002006-06-26 02:48:02 +02003670 curproxy = curproxy->next;
3671 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003672
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 if (cfgerr > 0) {
3674 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003675 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003677
3678 /*
3679 * Recount currently required checks.
3680 */
3681
3682 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3683 int optnum;
3684
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003685 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3686 if (curproxy->options & cfg_opts[optnum].val)
3687 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003688
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003689 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3690 if (curproxy->options2 & cfg_opts2[optnum].val)
3691 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003692 }
3693
Willy Tarreaua534fea2008-08-03 12:19:50 +02003694 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003695 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003696 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003697
3698 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003699 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003700 cursection = NULL;
3701 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702}
3703
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003704/*
3705 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3706 * parsing sessions.
3707 */
3708void cfg_register_keywords(struct cfg_kw_list *kwl)
3709{
3710 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3711}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003713/*
3714 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3715 */
3716void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3717{
3718 LIST_DEL(&kwl->list);
3719 LIST_INIT(&kwl->list);
3720}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721
3722/*
3723 * Local variables:
3724 * c-indent-level: 8
3725 * c-basic-offset: 8
3726 * End:
3727 */