blob: 8839e85ead515da8f2815ae92940ac06bb817927 [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 Tarreau66aa61f2009-01-18 21:44:07 +0100128 { NULL, 0, 0, 0 }
129};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130
Willy Tarreau6daf3432008-01-22 16:44:08 +0100131static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
133int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100134int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200135
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200136/* List head of all known configuration keywords */
137static struct cfg_kw_list cfg_keywords = {
138 .list = LIST_HEAD_INIT(cfg_keywords.list)
139};
140
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141/*
142 * converts <str> to a list of listeners which are dynamically allocated.
143 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
144 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
145 * - <port> is a numerical port from 1 to 65535 ;
146 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
147 * This can be repeated as many times as necessary, separated by a coma.
148 * The <tail> argument is a pointer to a current list which should be appended
149 * to the tail of the new list. The pointer to the new list is returned.
150 */
151static struct listener *str2listener(char *str, struct listener *tail)
152{
153 struct listener *l;
154 char *c, *next, *range, *dupstr;
155 int port, end;
156
157 next = dupstr = strdup(str);
158
159 while (next && *next) {
160 struct sockaddr_storage ss;
161
162 str = next;
163 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100164 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165 *next++ = 0;
166 }
167
168 /* 2) look for the addr/port delimiter, it's the last colon. */
169 if ((range = strrchr(str, ':')) == NULL) {
170 Alert("Missing port number: '%s'\n", str);
171 goto fail;
172 }
173
174 *range++ = 0;
175
176 if (strrchr(str, ':') != NULL) {
177 /* IPv6 address contains ':' */
178 memset(&ss, 0, sizeof(ss));
179 ss.ss_family = AF_INET6;
180
181 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
182 Alert("Invalid server address: '%s'\n", str);
183 goto fail;
184 }
185 }
186 else {
187 memset(&ss, 0, sizeof(ss));
188 ss.ss_family = AF_INET;
189
190 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
191 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
192 }
193 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
194 struct hostent *he;
195
196 if ((he = gethostbyname(str)) == NULL) {
197 Alert("Invalid server name: '%s'\n", str);
198 goto fail;
199 }
200 else
201 ((struct sockaddr_in *)&ss)->sin_addr =
202 *(struct in_addr *) *(he->h_addr_list);
203 }
204 }
205
206 /* 3) look for the port-end delimiter */
207 if ((c = strchr(range, '-')) != NULL) {
208 *c++ = 0;
209 end = atol(c);
210 }
211 else {
212 end = atol(range);
213 }
214
215 port = atol(range);
216
217 if (port < 1 || port > 65535) {
218 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
219 goto fail;
220 }
221
222 if (end < 1 || end > 65535) {
223 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
224 goto fail;
225 }
226
227 for (; port <= end; port++) {
228 l = (struct listener *)calloc(1, sizeof(struct listener));
229 l->next = tail;
230 tail = l;
231
232 l->fd = -1;
233 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100234 l->state = LI_INIT;
235
236 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100238 tcpv6_add_listener(l);
239 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100241 tcpv4_add_listener(l);
242 }
243 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244 } /* end for(port) */
245 } /* end while(next) */
246 free(dupstr);
247 return tail;
248 fail:
249 free(dupstr);
250 return NULL;
251}
252
Willy Tarreau977b8e42006-12-29 14:19:17 +0100253/*
254 * Sends a warning if proxy <proxy> does not have at least one of the
255 * capabilities in <cap>. An optionnal <hint> may be added at the end
256 * of the warning to help the user. Returns 1 if a warning was emitted
257 * or 0 if the condition is valid.
258 */
259int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
260{
261 char *msg;
262
263 switch (cap) {
264 case PR_CAP_BE: msg = "no backend"; break;
265 case PR_CAP_FE: msg = "no frontend"; break;
266 case PR_CAP_RS: msg = "no ruleset"; break;
267 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
268 default: msg = "not enough"; break;
269 }
270
271 if (!(proxy->cap & cap)) {
272 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100273 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100274 return 1;
275 }
276 return 0;
277}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278
Willy Tarreau61d18892009-03-31 10:49:21 +0200279/* Report a warning if a rule is placed after a 'block' rule.
280 * Return 1 if the warning has been emitted, otherwise 0.
281 */
282int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
283{
284 if (!LIST_ISEMPTY(&proxy->block_cond)) {
285 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
286 file, line, arg);
287 return 1;
288 }
289 return 0;
290}
291
292/* Report a warning if a rule is placed after a reqrewrite rule.
293 * Return 1 if the warning has been emitted, otherwise 0.
294 */
295int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
296{
297 if (proxy->req_exp) {
298 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
299 file, line, arg);
300 return 1;
301 }
302 return 0;
303}
304
305/* Report a warning if a rule is placed after a reqadd rule.
306 * Return 1 if the warning has been emitted, otherwise 0.
307 */
308int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
309{
310 if (proxy->nb_reqadd) {
311 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
312 file, line, arg);
313 return 1;
314 }
315 return 0;
316}
317
318/* Report a warning if a rule is placed after a redirect rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
321int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
322{
323 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a 'use_backend' rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
334int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
335{
336 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* report a warning if a block rule is dangerously placed */
345int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
346{
347 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
348 warnif_rule_after_reqadd(proxy, file, line, arg) ||
349 warnif_rule_after_redirect(proxy, file, line, arg) ||
350 warnif_rule_after_use_backend(proxy, file, line, arg);
351}
352
353/* report a warning if a reqxxx rule is dangerously placed */
354int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
355{
356 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
357 warnif_rule_after_redirect(proxy, file, line, arg) ||
358 warnif_rule_after_use_backend(proxy, file, line, arg);
359}
360
361/* report a warning if a reqadd rule is dangerously placed */
362int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
363{
364 return warnif_rule_after_redirect(proxy, file, line, arg) ||
365 warnif_rule_after_use_backend(proxy, file, line, arg);
366}
367
Willy Tarreaubaaee002006-06-26 02:48:02 +0200368/*
369 * parse a line in a <global> section. Returns 0 if OK, -1 if error.
370 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100371int cfg_parse_global(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200372{
373
374 if (!strcmp(args[0], "global")) { /* new section */
375 /* no option, nothing special to do */
376 return 0;
377 }
378 else if (!strcmp(args[0], "daemon")) {
379 global.mode |= MODE_DAEMON;
380 }
381 else if (!strcmp(args[0], "debug")) {
382 global.mode |= MODE_DEBUG;
383 }
384 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100385 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200386 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200387 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100388 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200389 }
390 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100391 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200393 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100394 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200395 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100396 else if (!strcmp(args[0], "nosplice")) {
397 global.tune.options &= ~GTUNE_USE_SPLICE;
398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399 else if (!strcmp(args[0], "quiet")) {
400 global.mode |= MODE_QUIET;
401 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200402 else if (!strcmp(args[0], "tune.maxpollevents")) {
403 if (global.tune.maxpollevents != 0) {
404 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
405 return 0;
406 }
407 if (*(args[1]) == 0) {
408 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
409 return -1;
410 }
411 global.tune.maxpollevents = atol(args[1]);
412 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100413 else if (!strcmp(args[0], "tune.maxaccept")) {
414 if (global.tune.maxaccept != 0) {
415 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
416 return 0;
417 }
418 if (*(args[1]) == 0) {
419 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
420 return -1;
421 }
422 global.tune.maxaccept = atol(args[1]);
423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200424 else if (!strcmp(args[0], "uid")) {
425 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200426 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200427 return 0;
428 }
429 if (*(args[1]) == 0) {
430 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
431 return -1;
432 }
433 global.uid = atol(args[1]);
434 }
435 else if (!strcmp(args[0], "gid")) {
436 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200437 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200438 return 0;
439 }
440 if (*(args[1]) == 0) {
441 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
442 return -1;
443 }
444 global.gid = atol(args[1]);
445 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200446 /* user/group name handling */
447 else if (!strcmp(args[0], "user")) {
448 struct passwd *ha_user;
449 if (global.uid != 0) {
450 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
451 return 0;
452 }
453 errno = 0;
454 ha_user = getpwnam(args[1]);
455 if (ha_user != NULL) {
456 global.uid = (int)ha_user->pw_uid;
457 }
458 else {
459 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
460 exit(1);
461 }
462 }
463 else if (!strcmp(args[0], "group")) {
464 struct group *ha_group;
465 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200466 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200467 return 0;
468 }
469 errno = 0;
470 ha_group = getgrnam(args[1]);
471 if (ha_group != NULL) {
472 global.gid = (int)ha_group->gr_gid;
473 }
474 else {
475 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
476 exit(1);
477 }
478 }
479 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 else if (!strcmp(args[0], "nbproc")) {
481 if (global.nbproc != 0) {
482 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
483 return 0;
484 }
485 if (*(args[1]) == 0) {
486 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
487 return -1;
488 }
489 global.nbproc = atol(args[1]);
490 }
491 else if (!strcmp(args[0], "maxconn")) {
492 if (global.maxconn != 0) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 return 0;
495 }
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
498 return -1;
499 }
500 global.maxconn = atol(args[1]);
501#ifdef SYSTEM_MAXCONN
502 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
503 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);
504 global.maxconn = DEFAULT_MAXCONN;
505 }
506#endif /* SYSTEM_MAXCONN */
507 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100508 else if (!strcmp(args[0], "maxpipes")) {
509 if (global.maxpipes != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
511 return 0;
512 }
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
515 return -1;
516 }
517 global.maxpipes = atol(args[1]);
518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200519 else if (!strcmp(args[0], "ulimit-n")) {
520 if (global.rlimit_nofile != 0) {
521 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
522 return 0;
523 }
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 return -1;
527 }
528 global.rlimit_nofile = atol(args[1]);
529 }
530 else if (!strcmp(args[0], "chroot")) {
531 if (global.chroot != NULL) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
533 return 0;
534 }
535 if (*(args[1]) == 0) {
536 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
537 return -1;
538 }
539 global.chroot = strdup(args[1]);
540 }
541 else if (!strcmp(args[0], "pidfile")) {
542 if (global.pidfile != NULL) {
543 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
544 return 0;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
548 return -1;
549 }
550 global.pidfile = strdup(args[1]);
551 }
552 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100553 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554 int facility, level;
555
556 if (*(args[1]) == 0 || *(args[2]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
558 return -1;
559 }
560
561 facility = get_log_facility(args[2]);
562 if (facility < 0) {
563 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
564 exit(1);
565 }
566
567 level = 7; /* max syslog level = debug */
568 if (*(args[3])) {
569 level = get_log_level(args[3]);
570 if (level < 0) {
571 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
572 exit(1);
573 }
574 }
575
Robert Tsai81ae1952007-12-05 10:47:29 +0100576 if (args[1][0] == '/') {
577 logsrv.u.addr.sa_family = AF_UNIX;
578 logsrv.u.un = *str2sun(args[1]);
579 } else {
580 logsrv.u.addr.sa_family = AF_INET;
581 logsrv.u.in = *str2sa(args[1]);
582 if (!logsrv.u.in.sin_port)
583 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585
586 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100587 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 global.logfac1 = facility;
589 global.loglev1 = level;
590 }
591 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100592 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 global.logfac2 = facility;
594 global.loglev2 = level;
595 }
596 else {
597 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
598 return -1;
599 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200600 }
601 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
602 if (global.spread_checks != 0) {
603 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
604 return 0;
605 }
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
608 return -1;
609 }
610 global.spread_checks = atol(args[1]);
611 if (global.spread_checks < 0 || global.spread_checks > 50) {
612 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
613 return -1;
614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
616 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200617 struct cfg_kw_list *kwl;
618 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200619 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200620
621 list_for_each_entry(kwl, &cfg_keywords.list, list) {
622 for (index = 0; kwl->kw[index].kw != NULL; index++) {
623 if (kwl->kw[index].section != CFG_GLOBAL)
624 continue;
625 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
626 /* prepare error message just in case */
627 snprintf(trash, sizeof(trash),
628 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200629 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
630 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200631 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
632 return -1;
633 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200634 else if (rc > 0) {
635 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
636 return 0;
637 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200638 return 0;
639 }
640 }
641 }
642
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
644 return -1;
645 }
646 return 0;
647}
648
649
650static void init_default_instance()
651{
652 memset(&defproxy, 0, sizeof(defproxy));
653 defproxy.mode = PR_MODE_TCP;
654 defproxy.state = PR_STNEW;
655 defproxy.maxconn = cfg_maxpconn;
656 defproxy.conn_retries = CONN_RETRIES;
657 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Willy Tarreaub099aca2008-10-12 17:26:37 +0200658
659 LIST_INIT(&defproxy.pendconns);
660 LIST_INIT(&defproxy.acl);
661 LIST_INIT(&defproxy.block_cond);
662 LIST_INIT(&defproxy.mon_fail_cond);
663 LIST_INIT(&defproxy.switching_rules);
664
Willy Tarreau3a70f942008-02-15 11:15:34 +0100665 proxy_reset_timeouts(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666}
667
668/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100669 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
670 * Returns 0 if OK, -1 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100672int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200673{
674 static struct proxy *curproxy = NULL;
675 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200676 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100677 int rc;
678 unsigned val;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679
Willy Tarreau977b8e42006-12-29 14:19:17 +0100680 if (!strcmp(args[0], "listen"))
681 rc = PR_CAP_LISTEN;
682 else if (!strcmp(args[0], "frontend"))
683 rc = PR_CAP_FE | PR_CAP_RS;
684 else if (!strcmp(args[0], "backend"))
685 rc = PR_CAP_BE | PR_CAP_RS;
686 else if (!strcmp(args[0], "ruleset"))
687 rc = PR_CAP_RS;
688 else
689 rc = PR_CAP_NONE;
690
691 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 if (!*args[1]) {
693 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
694 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
695 file, linenum, args[0]);
696 return -1;
697 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200698
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100699 err = invalid_char(args[1]);
700 if (err) {
701 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
702 file, linenum, *err, args[0], args[1]);
703 return -1;
704 }
705
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200706 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
707 /*
708 * If there are two proxies with the same name only following
709 * combinations are allowed:
710 *
711 * listen backend frontend ruleset
712 * listen - - - -
713 * backend - - OK -
714 * frontend - OK - -
715 * ruleset - - - -
716 */
717
718 if (!strcmp(curproxy->id, args[1]) &&
719 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
720 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau816eb542007-11-04 07:04:43 +0100721 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s.\n",
722 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy));
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200723 }
724 }
725
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
727 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
728 return -1;
729 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100730
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 curproxy->next = proxy;
732 proxy = curproxy;
733 LIST_INIT(&curproxy->pendconns);
Willy Tarreaueb0c6142007-05-07 00:53:22 +0200734 LIST_INIT(&curproxy->acl);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +0200735 LIST_INIT(&curproxy->block_cond);
Willy Tarreaub463dfb2008-06-07 23:08:56 +0200736 LIST_INIT(&curproxy->redirect_rules);
Willy Tarreaub80c2302007-11-30 20:51:32 +0100737 LIST_INIT(&curproxy->mon_fail_cond);
Willy Tarreau55ea7572007-06-17 19:56:27 +0200738 LIST_INIT(&curproxy->switching_rules);
Willy Tarreaub6866442008-07-14 23:54:42 +0200739 LIST_INIT(&curproxy->tcp_req.inspect_rules);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740
Willy Tarreauee991362007-05-14 14:37:50 +0200741 /* Timeouts are defined as -1, so we cannot use the zeroed area
742 * as a default value.
743 */
Willy Tarreau3a70f942008-02-15 11:15:34 +0100744 proxy_reset_timeouts(curproxy);
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200745
746 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100748 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749
750 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100751 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 curproxy->listen = str2listener(args[2], curproxy->listen);
753 if (!curproxy->listen)
754 return -1;
755 global.maxsock++;
756 }
757
758 /* set default values */
759 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100761 curproxy->options2 = defproxy.options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100762 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100763 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200764 curproxy->except_net = defproxy.except_net;
765 curproxy->except_mask = defproxy.except_mask;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200767 if (defproxy.fwdfor_hdr_len) {
768 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
769 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
770 }
771
Willy Tarreau977b8e42006-12-29 14:19:17 +0100772 if (curproxy->cap & PR_CAP_FE) {
773 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +0100774 curproxy->backlog = defproxy.backlog;
Willy Tarreau39af0f62009-03-07 11:53:44 +0100775 curproxy->fe_maxsps = defproxy.fe_maxsps;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100776
777 /* initialize error relocations */
778 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
779 if (defproxy.errmsg[rc].str)
780 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
781 }
782
783 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
784 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785
Willy Tarreau977b8e42006-12-29 14:19:17 +0100786 if (curproxy->cap & PR_CAP_BE) {
787 curproxy->fullconn = defproxy.fullconn;
788 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789
Willy Tarreau977b8e42006-12-29 14:19:17 +0100790 if (defproxy.check_req)
791 curproxy->check_req = strdup(defproxy.check_req);
792 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793
Willy Tarreau977b8e42006-12-29 14:19:17 +0100794 if (defproxy.cookie_name)
795 curproxy->cookie_name = strdup(defproxy.cookie_name);
796 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau01732802007-11-01 22:48:15 +0100797
798 if (defproxy.url_param_name)
799 curproxy->url_param_name = strdup(defproxy.url_param_name);
800 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100801
802 if (defproxy.iface_name)
803 curproxy->iface_name = strdup(defproxy.iface_name);
804 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806
Willy Tarreau977b8e42006-12-29 14:19:17 +0100807 if (curproxy->cap & PR_CAP_RS) {
808 if (defproxy.capture_name)
809 curproxy->capture_name = strdup(defproxy.capture_name);
810 curproxy->capture_namelen = defproxy.capture_namelen;
811 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +0100812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813
Willy Tarreau977b8e42006-12-29 14:19:17 +0100814 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100815 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100816 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +0100817 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100818 curproxy->uri_auth = defproxy.uri_auth;
819 curproxy->mon_net = defproxy.mon_net;
820 curproxy->mon_mask = defproxy.mon_mask;
821 if (defproxy.monitor_uri)
822 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
823 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100824 if (defproxy.defbe.name)
825 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100826 }
827
828 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +0100829 curproxy->timeout.connect = defproxy.timeout.connect;
830 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +0100831 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +0100832 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +0100833 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100834 curproxy->source_addr = defproxy.source_addr;
835 }
836
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 curproxy->mode = defproxy.mode;
838 curproxy->logfac1 = defproxy.logfac1;
839 curproxy->logsrv1 = defproxy.logsrv1;
840 curproxy->loglev1 = defproxy.loglev1;
841 curproxy->logfac2 = defproxy.logfac2;
842 curproxy->logsrv2 = defproxy.logsrv2;
843 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 curproxy->grace = defproxy.grace;
Willy Tarreaudcd47712007-11-04 23:35:08 +0100845 curproxy->uuid = next_pxid++; /* generate a uuid for this proxy */
846 curproxy->next_svid = 1; /* server id 0 is reserved */
Willy Tarreau1c47f852006-07-09 08:22:27 +0200847
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 return 0;
849 }
850 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
851 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +0100852 /* FIXME-20070101: we should do this too at the end of the
853 * config parsing to free all default values.
854 */
Willy Tarreaua534fea2008-08-03 12:19:50 +0200855 free(defproxy.check_req);
856 free(defproxy.cookie_name);
857 free(defproxy.url_param_name);
858 free(defproxy.capture_name);
859 free(defproxy.monitor_uri);
860 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +0100861 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +0200862 free(defproxy.fwdfor_hdr_name);
863 defproxy.fwdfor_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +0100864
Willy Tarreaua534fea2008-08-03 12:19:50 +0200865 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
866 free(defproxy.errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +0100867
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868 /* we cannot free uri_auth because it might already be used */
869 init_default_instance();
870 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +0100871 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 return 0;
873 }
874 else if (curproxy == NULL) {
875 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
876 return -1;
877 }
878
Willy Tarreau977b8e42006-12-29 14:19:17 +0100879
880 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100882 struct listener *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100883 int cur_arg;
884
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 if (curproxy == &defproxy) {
886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
887 return -1;
888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
890 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891
892 if (strchr(args[1], ':') == NULL) {
893 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
894 file, linenum, args[0]);
895 return -1;
896 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100897
898 last_listen = curproxy->listen;
899 curproxy->listen = str2listener(args[1], last_listen);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 if (!curproxy->listen)
901 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100902
903 cur_arg = 2;
904 while (*(args[cur_arg])) {
905 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
906#ifdef SO_BINDTODEVICE
907 struct listener *l;
908
909 if (!*args[cur_arg + 1]) {
910 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
911 file, linenum, args[0]);
912 return -1;
913 }
914
915 for (l = curproxy->listen; l != last_listen; l = l->next)
916 l->interface = strdup(args[cur_arg + 1]);
917
918 global.last_checks |= LSTCHK_NETADM;
919
920 cur_arg += 2;
921 continue;
922#else
923 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
924 file, linenum, args[0], args[cur_arg]);
925 return -1;
926#endif
927 }
928 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100929#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100930 struct listener *l;
931
932 for (l = curproxy->listen; l != last_listen; l = l->next)
933 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100934
935 cur_arg ++;
936 continue;
937#else
938 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
939 file, linenum, args[0], args[cur_arg]);
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100940 return -1;
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100941#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100942 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +0100943 Alert("parsing [%s:%d] : '%s' only supports the 'transparent' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100944 file, linenum, args[0]);
945 return -1;
Willy Tarreaub1e52e82008-01-13 14:49:51 +0100946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 global.maxsock++;
948 return 0;
949 }
950 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
951 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
952 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
953 file, linenum, args[0]);
954 return -1;
955 }
Willy Tarreau977b8e42006-12-29 14:19:17 +0100956 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
957 return 0;
958
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 /* flush useless bits */
960 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
961 return 0;
962 }
Willy Tarreau1c47f852006-07-09 08:22:27 +0200963 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100964 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
965 return 0;
966
Willy Tarreau1c47f852006-07-09 08:22:27 +0200967 if (!*args[1]) {
968 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
969 file, linenum, args[0]);
970 return -1;
971 }
972
Willy Tarreaua534fea2008-08-03 12:19:50 +0200973 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100974 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200975 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100976 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +0200977 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
978
979 return 0;
980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
982 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
983 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
984 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
985 else {
986 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
987 return -1;
988 }
989 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +0100990 else if (!strcmp(args[0], "id")) {
991 struct proxy *target;
992
993 if (curproxy == &defproxy) {
994 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
995 file, linenum, args[0]);
996 return -1;
997 }
998
999 if (!*args[1]) {
1000 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1001 file, linenum, args[0]);
1002 return -1;
1003 }
1004
1005 curproxy->uuid = atol(args[1]);
1006
1007 if (curproxy->uuid < 1001) {
1008 Alert("parsing [%s:%d]: custom id has to be > 1000",
1009 file, linenum);
1010 return -1;
1011 }
1012
1013 for (target = proxy; target; target = target->next)
1014 if (curproxy != target && curproxy->uuid == target->uuid) {
1015 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1016 file, linenum, curproxy->id, target->id);
1017 return -1;
1018 }
1019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1021 curproxy->state = PR_STSTOPPED;
1022 }
1023 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1024 curproxy->state = PR_STNEW;
1025 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001026 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1027 int cur_arg = 1;
1028 unsigned int set = 0;
1029
1030 while (*args[cur_arg]) {
1031 int u;
1032 if (strcmp(args[cur_arg], "all") == 0) {
1033 set = 0;
1034 break;
1035 }
1036 else if (strcmp(args[cur_arg], "odd") == 0) {
1037 set |= 0x55555555;
1038 }
1039 else if (strcmp(args[cur_arg], "even") == 0) {
1040 set |= 0xAAAAAAAA;
1041 }
1042 else {
1043 u = str2uic(args[cur_arg]);
1044 if (u < 1 || u > 32) {
1045 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1046 file, linenum, args[0]);
1047 return -1;
1048 }
1049 if (u > global.nbproc) {
1050 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1051 file, linenum, args[0]);
1052 }
1053 set |= 1 << (u - 1);
1054 }
1055 cur_arg++;
1056 }
1057 curproxy->bind_proc = set;
1058 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001059 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001060 if (curproxy == &defproxy) {
1061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1062 return -1;
1063 }
1064
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001065 err = invalid_char(args[1]);
1066 if (err) {
1067 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1068 file, linenum, *err, args[1]);
1069 return -1;
1070 }
1071
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001072 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1073 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1074 file, linenum, args[1]);
1075 return -1;
1076 }
1077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1079 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080
Willy Tarreau977b8e42006-12-29 14:19:17 +01001081 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1082 return 0;
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1086 file, linenum, args[0]);
1087 return -1;
1088 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001089
1090 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 curproxy->cookie_name = strdup(args[1]);
1092 curproxy->cookie_len = strlen(curproxy->cookie_name);
1093
1094 cur_arg = 2;
1095 while (*(args[cur_arg])) {
1096 if (!strcmp(args[cur_arg], "rewrite")) {
1097 curproxy->options |= PR_O_COOK_RW;
1098 }
1099 else if (!strcmp(args[cur_arg], "indirect")) {
1100 curproxy->options |= PR_O_COOK_IND;
1101 }
1102 else if (!strcmp(args[cur_arg], "insert")) {
1103 curproxy->options |= PR_O_COOK_INS;
1104 }
1105 else if (!strcmp(args[cur_arg], "nocache")) {
1106 curproxy->options |= PR_O_COOK_NOC;
1107 }
1108 else if (!strcmp(args[cur_arg], "postonly")) {
1109 curproxy->options |= PR_O_COOK_POST;
1110 }
1111 else if (!strcmp(args[cur_arg], "prefix")) {
1112 curproxy->options |= PR_O_COOK_PFX;
1113 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001114 else if (!strcmp(args[cur_arg], "domain")) {
1115 if (!*args[cur_arg + 1]) {
1116 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1117 file, linenum, args[cur_arg]);
1118 return -1;
1119 }
1120
1121 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
1122 /* rfc2109, 4.3.2 Rejecting Cookies */
1123 Alert("parsing [%s:%d]: domain '%s' contains no embedded"
1124 " dots or does not start with a dot.\n",
1125 file, linenum, args[cur_arg + 1]);
1126 return -1;
1127 }
1128
1129 err = invalid_domainchar(args[cur_arg + 1]);
1130 if (err) {
1131 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1132 file, linenum, *err, args[cur_arg + 1]);
1133 return -1;
1134 }
1135
Krzysztof Piotr Oledzki1acf2172008-05-29 23:03:34 +02001136 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001137 cur_arg++;
1138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001140 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 file, linenum, args[0]);
1142 return -1;
1143 }
1144 cur_arg++;
1145 }
1146 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1147 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1148 file, linenum);
1149 return -1;
1150 }
1151
1152 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1153 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1154 file, linenum);
1155 return -1;
1156 }
1157 }/* end else if (!strcmp(args[0], "cookie")) */
1158 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1161 return 0;
1162
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 if (*(args[5]) == 0) {
1164 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout>.\n",
1165 file, linenum, args[0]);
1166 return -1;
1167 }
1168 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001169 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 curproxy->appsession_name = strdup(args[1]);
1171 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1172 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001173 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1174 if (err) {
1175 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1176 file, linenum, *err, args[0]);
1177 return -1;
1178 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001179 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001180
Willy Tarreau51041c72007-09-09 21:56:53 +02001181 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1182 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 return -1;
1184 }
1185 } /* Url App Session */
1186 else if (!strcmp(args[0], "capture")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001187 if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
1188 return 0;
1189
Willy Tarreaubaaee002006-06-26 02:48:02 +02001190 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 if (*(args[4]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1193 file, linenum, args[0]);
1194 return -1;
1195 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001196 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 curproxy->capture_name = strdup(args[2]);
1198 curproxy->capture_namelen = strlen(curproxy->capture_name);
1199 curproxy->capture_len = atol(args[4]);
1200 if (curproxy->capture_len >= CAPTURE_LEN) {
1201 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1202 file, linenum, CAPTURE_LEN - 1);
1203 curproxy->capture_len = CAPTURE_LEN - 1;
1204 }
1205 curproxy->to_log |= LW_COOKIE;
1206 }
1207 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1208 struct cap_hdr *hdr;
1209
1210 if (curproxy == &defproxy) {
1211 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1212 return -1;
1213 }
1214
1215 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1216 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1217 file, linenum, args[0], args[1]);
1218 return -1;
1219 }
1220
1221 hdr = calloc(sizeof(struct cap_hdr), 1);
1222 hdr->next = curproxy->req_cap;
1223 hdr->name = strdup(args[3]);
1224 hdr->namelen = strlen(args[3]);
1225 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001226 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 hdr->index = curproxy->nb_req_cap++;
1228 curproxy->req_cap = hdr;
1229 curproxy->to_log |= LW_REQHDR;
1230 }
1231 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1232 struct cap_hdr *hdr;
1233
1234 if (curproxy == &defproxy) {
1235 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1236 return -1;
1237 }
1238
1239 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1240 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1241 file, linenum, args[0], args[1]);
1242 return -1;
1243 }
1244 hdr = calloc(sizeof(struct cap_hdr), 1);
1245 hdr->next = curproxy->rsp_cap;
1246 hdr->name = strdup(args[3]);
1247 hdr->namelen = strlen(args[3]);
1248 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001249 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001250 hdr->index = curproxy->nb_rsp_cap++;
1251 curproxy->rsp_cap = hdr;
1252 curproxy->to_log |= LW_RSPHDR;
1253 }
1254 else {
1255 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1256 file, linenum, args[0]);
1257 return -1;
1258 }
1259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001260 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001261 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1262 return 0;
1263
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 if (*(args[1]) == 0) {
1265 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1266 file, linenum, args[0]);
1267 return -1;
1268 }
1269 curproxy->conn_retries = atol(args[1]);
1270 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001271 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1272 int pol = ACL_COND_NONE;
1273 struct acl_cond *cond;
1274
Willy Tarreaub099aca2008-10-12 17:26:37 +02001275 if (curproxy == &defproxy) {
1276 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1277 return -1;
1278 }
1279
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001280 if (!strcmp(args[1], "if"))
1281 pol = ACL_COND_IF;
1282 else if (!strcmp(args[1], "unless"))
1283 pol = ACL_COND_UNLESS;
1284
1285 if (pol == ACL_COND_NONE) {
1286 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1287 file, linenum, args[0]);
1288 return -1;
1289 }
1290
1291 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1292 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1293 file, linenum);
1294 return -1;
1295 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001296 cond->line = linenum;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001297 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001298 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001299 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001300 else if (!strcmp(args[0], "redirect")) {
1301 int pol = ACL_COND_NONE;
1302 struct acl_cond *cond;
1303 struct redirect_rule *rule;
1304 int cur_arg;
1305 int type = REDIRECT_TYPE_NONE;
1306 int code = 302;
1307 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001308 char *cookie = NULL;
1309 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001310 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001311
1312 cur_arg = 1;
1313 while (*(args[cur_arg])) {
1314 if (!strcmp(args[cur_arg], "location")) {
1315 if (!*args[cur_arg + 1]) {
1316 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1317 file, linenum, args[0], args[cur_arg]);
1318 return -1;
1319 }
1320
1321 type = REDIRECT_TYPE_LOCATION;
1322 cur_arg++;
1323 destination = args[cur_arg];
1324 }
1325 else if (!strcmp(args[cur_arg], "prefix")) {
1326 if (!*args[cur_arg + 1]) {
1327 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1328 file, linenum, args[0], args[cur_arg]);
1329 return -1;
1330 }
1331
1332 type = REDIRECT_TYPE_PREFIX;
1333 cur_arg++;
1334 destination = args[cur_arg];
1335 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001336 else if (!strcmp(args[cur_arg], "set-cookie")) {
1337 if (!*args[cur_arg + 1]) {
1338 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1339 file, linenum, args[0], args[cur_arg]);
1340 return -1;
1341 }
1342
1343 cur_arg++;
1344 cookie = args[cur_arg];
1345 cookie_set = 1;
1346 }
1347 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1348 if (!*args[cur_arg + 1]) {
1349 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1350 file, linenum, args[0], args[cur_arg]);
1351 return -1;
1352 }
1353
1354 cur_arg++;
1355 cookie = args[cur_arg];
1356 cookie_set = 0;
1357 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001358 else if (!strcmp(args[cur_arg],"code")) {
1359 if (!*args[cur_arg + 1]) {
1360 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1361 file, linenum, args[0]);
1362 return -1;
1363 }
1364 cur_arg++;
1365 code = atol(args[cur_arg]);
1366 if (code < 301 || code > 303) {
1367 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1368 file, linenum, args[0], code);
1369 return -1;
1370 }
1371 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001372 else if (!strcmp(args[cur_arg],"drop-query")) {
1373 flags |= REDIRECT_FLAG_DROP_QS;
1374 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001375 else if (!strcmp(args[cur_arg], "if")) {
1376 pol = ACL_COND_IF;
1377 cur_arg++;
1378 break;
1379 }
1380 else if (!strcmp(args[cur_arg], "unless")) {
1381 pol = ACL_COND_UNLESS;
1382 cur_arg++;
1383 break;
1384 }
1385 else {
1386 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix' or 'location' (was '%s').\n",
1387 file, linenum, args[0], args[cur_arg]);
1388 return -1;
1389 }
1390 cur_arg++;
1391 }
1392
1393 if (type == REDIRECT_TYPE_NONE) {
1394 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1395 file, linenum, args[0]);
1396 return -1;
1397 }
1398
1399 if (pol == ACL_COND_NONE) {
1400 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1401 file, linenum, args[0]);
1402 return -1;
1403 }
1404
1405 if ((cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
1406 Alert("parsing [%s:%d] : '%s': error detected while parsing condition.\n",
1407 file, linenum, args[0]);
1408 return -1;
1409 }
1410
Willy Tarreaua9802632008-07-25 19:13:19 +02001411 cond->line = linenum;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001412 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1413 rule->cond = cond;
1414 rule->rdr_str = strdup(destination);
1415 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001416 if (cookie) {
1417 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1418 * a clear consists in appending "; Max-Age=0" at the end.
1419 */
1420 rule->cookie_len = strlen(cookie);
1421 if (cookie_set)
1422 rule->cookie_str = strdup(cookie);
1423 else {
1424 rule->cookie_str = malloc(rule->cookie_len + 12);
1425 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1426 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1427 rule->cookie_len += 11;
1428 }
1429 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001430 rule->type = type;
1431 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001432 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001433 LIST_INIT(&rule->list);
1434 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001435 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001436 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001437 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001438 int pol = ACL_COND_NONE;
1439 struct acl_cond *cond;
1440 struct switching_rule *rule;
1441
Willy Tarreaub099aca2008-10-12 17:26:37 +02001442 if (curproxy == &defproxy) {
1443 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1444 return -1;
1445 }
1446
Willy Tarreau55ea7572007-06-17 19:56:27 +02001447 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1448 return 0;
1449
1450 if (*(args[1]) == 0) {
1451 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1452 return -1;
1453 }
1454
1455 if (!strcmp(args[2], "if"))
1456 pol = ACL_COND_IF;
1457 else if (!strcmp(args[2], "unless"))
1458 pol = ACL_COND_UNLESS;
1459
1460 if (pol == ACL_COND_NONE) {
1461 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1462 file, linenum, args[0]);
1463 return -1;
1464 }
1465
1466 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02001467 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02001468 file, linenum);
1469 return -1;
1470 }
1471
Willy Tarreaua9802632008-07-25 19:13:19 +02001472 cond->line = linenum;
1473 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02001474 struct acl *acl;
1475 const char *name;
1476
1477 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
1478 name = acl ? acl->name : "(unknown)";
1479 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
1480 file, linenum, name);
Willy Tarreaua9802632008-07-25 19:13:19 +02001481 }
1482
Willy Tarreau55ea7572007-06-17 19:56:27 +02001483 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
1484 rule->cond = cond;
1485 rule->be.name = strdup(args[1]);
1486 LIST_INIT(&rule->list);
1487 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001490 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1491 return 0;
1492
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1494 curproxy->uri_auth = NULL; /* we must detach from the default config */
1495
1496 if (*(args[1]) == 0) {
1497 Alert("parsing [%s:%d] : '%s' expects 'uri', 'realm', 'auth', 'scope' or 'enable'.\n", file, linenum, args[0]);
1498 return -1;
1499 } else if (!strcmp(args[1], "uri")) {
1500 if (*(args[2]) == 0) {
1501 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1502 return -1;
1503 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1505 return -1;
1506 }
1507 } else if (!strcmp(args[1], "realm")) {
1508 if (*(args[2]) == 0) {
1509 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1510 return -1;
1511 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1512 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1513 return -1;
1514 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02001515 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001516 unsigned interval;
1517
1518 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
1519 if (err) {
1520 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
1521 file, linenum, *err);
Willy Tarreaubbd42122007-07-25 07:26:38 +02001522 return -1;
1523 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1524 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1525 return -1;
1526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 } else if (!strcmp(args[1], "auth")) {
1528 if (*(args[2]) == 0) {
1529 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1530 return -1;
1531 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1532 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1533 return -1;
1534 }
1535 } else if (!strcmp(args[1], "scope")) {
1536 if (*(args[2]) == 0) {
1537 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1538 return -1;
1539 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1540 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1541 return -1;
1542 }
1543 } else if (!strcmp(args[1], "enable")) {
1544 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1545 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1546 return -1;
1547 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001548 } else if (!strcmp(args[1], "hide-version")) {
1549 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
1550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1551 return -1;
1552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 } else {
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02001554 Alert("parsing [%s:%d] : unknown stats parameter '%s' (expects 'hide-version', 'uri', 'realm', 'auth' or 'enable').\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 file, linenum, args[0]);
1556 return -1;
1557 }
1558 }
1559 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001560 int optnum;
1561
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001562 if (*(args[1]) == '\0') {
1563 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
1564 file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 return -1;
1566 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01001567
1568 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1569 if (!strcmp(args[1], cfg_opts[optnum].name)) {
1570 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL))
1571 return 0;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001572
1573 if (!inv)
1574 curproxy->options |= cfg_opts[optnum].val;
1575 else
1576 curproxy->options &= ~cfg_opts[optnum].val;
1577
Willy Tarreau13943ab2006-12-31 00:24:10 +01001578 return 0;
1579 }
1580 }
1581
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001582 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
1583 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
1584 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL))
1585 return 0;
1586
1587 if (!inv)
1588 curproxy->options2 |= cfg_opts2[optnum].val;
1589 else
1590 curproxy->options2 &= ~cfg_opts2[optnum].val;
1591
1592 return 0;
1593 }
1594 }
1595
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001596 if (inv) {
1597 Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n",
1598 file, linenum, args[1]);
1599 return -1;
1600 }
1601
Willy Tarreau13943ab2006-12-31 00:24:10 +01001602 if (!strcmp(args[1], "httplog"))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 /* generate a complete HTTP log */
1604 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
1605 else if (!strcmp(args[1], "tcplog"))
1606 /* generate a detailed TCP log */
1607 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608 else if (!strcmp(args[1], "tcpka")) {
1609 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001610 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
1611 return 0;
1612
1613 if (curproxy->cap & PR_CAP_FE)
1614 curproxy->options |= PR_O_TCP_CLI_KA;
1615 if (curproxy->cap & PR_CAP_BE)
1616 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 }
1618 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01001619 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1620 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001622 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001623 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001624 curproxy->options &= ~PR_O_SMTP_CHK;
1625 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 if (!*args[2]) { /* no argument */
1627 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
1628 curproxy->check_len = strlen(DEF_CHECK_REQ);
1629 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02001630 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 curproxy->check_req = (char *)malloc(reqlen);
1632 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1633 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
1634 } else { /* more arguments : METHOD URI [HTTP_VER] */
1635 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
1636 if (*args[4])
1637 reqlen += strlen(args[4]);
1638 else
1639 reqlen += strlen("HTTP/1.0");
1640
1641 curproxy->check_req = (char *)malloc(reqlen);
1642 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1643 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
1644 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02001645 }
1646 else if (!strcmp(args[1], "ssl-hello-chk")) {
1647 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01001648 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
1649 return 0;
1650
Willy Tarreaua534fea2008-08-03 12:19:50 +02001651 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02001652 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02001653 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02001654 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Willy Tarreau23677902007-05-08 23:50:35 +02001656 else if (!strcmp(args[1], "smtpchk")) {
1657 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001658 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02001659 curproxy->options &= ~PR_O_HTTP_CHK;
1660 curproxy->options &= ~PR_O_SSL3_CHK;
1661 curproxy->options |= PR_O_SMTP_CHK;
1662
1663 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
1664 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1665 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1666 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
1667 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
1668 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
1669 curproxy->check_req = (char *)malloc(reqlen);
1670 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
1671 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
1672 } else {
1673 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
1674 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
1675 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
1676 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
1677 }
1678 }
1679 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001680 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02001681 int cur_arg;
1682
1683 /* insert x-forwarded-for field, but not for the IP address listed as an except.
1684 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001685 */
Ross Westaf72a1d2008-08-03 10:51:45 +02001686
1687 curproxy->options |= PR_O_FWDFOR;
1688
1689 free(curproxy->fwdfor_hdr_name);
1690 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
1691 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
1692
1693 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
1694 cur_arg = 2;
1695 while (*(args[cur_arg])) {
1696 if (!strcmp(args[cur_arg], "except")) {
1697 /* suboption except - needs additional argument for it */
1698 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
1699 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
1700 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001701 return -1;
1702 }
1703 /* flush useless bits */
1704 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02001705 cur_arg += 2;
1706 } else if (!strcmp(args[cur_arg], "header")) {
1707 /* suboption header - needs additional argument for it */
1708 if (*(args[cur_arg+1]) == 0) {
1709 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
1710 file, linenum, args[0], args[1], args[cur_arg]);
1711 return -1;
1712 }
1713 free(curproxy->fwdfor_hdr_name);
1714 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
1715 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
1716 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001717 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02001718 /* unknown suboption - catchall */
1719 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
1720 file, linenum, args[0], args[1]);
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001721 return -1;
1722 }
Ross Westaf72a1d2008-08-03 10:51:45 +02001723 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 else {
1726 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
1727 return -1;
1728 }
1729 return 0;
1730 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001731 else if (!strcmp(args[0], "default_backend")) {
1732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1733 return 0;
1734
1735 if (*(args[1]) == 0) {
1736 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1737 return -1;
1738 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001739 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001740 curproxy->defbe.name = strdup(args[1]);
1741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1744 return 0;
1745
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01001746 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
1747 file, linenum, args[0]);
1748
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 /* enable reconnections to dispatch */
1750 curproxy->options |= PR_O_REDISP;
1751 }
Willy Tarreau48494c02007-11-30 10:41:39 +01001752 else if (!strcmp(args[0], "http-check")) {
1753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1754 return 0;
1755
1756 if (strcmp(args[1], "disable-on-404") == 0) {
1757 /* enable a graceful server shutdown on an HTTP 404 response */
1758 curproxy->options |= PR_O_DISABLE404;
1759 }
1760 else {
1761 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
1762 return -1;
1763 }
1764 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01001765 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02001766 if (curproxy == &defproxy) {
1767 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1768 return -1;
1769 }
1770
Willy Tarreaub80c2302007-11-30 20:51:32 +01001771 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1772 return 0;
1773
1774 if (strcmp(args[1], "fail") == 0) {
1775 /* add a condition to fail monitor requests */
1776 int pol = ACL_COND_NONE;
1777 struct acl_cond *cond;
1778
1779 if (!strcmp(args[2], "if"))
1780 pol = ACL_COND_IF;
1781 else if (!strcmp(args[2], "unless"))
1782 pol = ACL_COND_UNLESS;
1783
1784 if (pol == ACL_COND_NONE) {
1785 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1786 file, linenum, args[0], args[1]);
1787 return -1;
1788 }
1789
1790 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
1791 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
1792 file, linenum, args[0], args[1]);
1793 return -1;
1794 }
Willy Tarreaua9802632008-07-25 19:13:19 +02001795 cond->line = linenum;
Willy Tarreaub80c2302007-11-30 20:51:32 +01001796 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
1797 }
1798 else {
1799 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
1800 return -1;
1801 }
1802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803#ifdef TPROXY
1804 else if (!strcmp(args[0], "transparent")) {
1805 /* enable transparent proxy connections */
1806 curproxy->options |= PR_O_TRANSP;
1807 }
1808#endif
1809 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
1811 return 0;
1812
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 if (*(args[1]) == 0) {
1814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1815 return -1;
1816 }
1817 curproxy->maxconn = atol(args[1]);
1818 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001819 else if (!strcmp(args[0], "backlog")) { /* backlog */
1820 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1821 return 0;
1822
1823 if (*(args[1]) == 0) {
1824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1825 return -1;
1826 }
1827 curproxy->backlog = atol(args[1]);
1828 }
Willy Tarreau86034312006-12-29 00:10:33 +01001829 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001830 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
1831 return 0;
1832
Willy Tarreau86034312006-12-29 00:10:33 +01001833 if (*(args[1]) == 0) {
1834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1835 return -1;
1836 }
1837 curproxy->fullconn = atol(args[1]);
1838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
1840 if (*(args[1]) == 0) {
1841 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
1842 return -1;
1843 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001844 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1845 if (err) {
1846 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
1847 file, linenum, *err);
1848 return -1;
1849 }
1850 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 }
1852 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
1853 if (curproxy == &defproxy) {
1854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1855 return -1;
1856 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1858 return 0;
1859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 if (strchr(args[1], ':') == NULL) {
1861 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
1862 return -1;
1863 }
1864 curproxy->dispatch_addr = *str2sa(args[1]);
1865 }
1866 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001867 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1868 return 0;
1869
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02001870 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01001871 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
1872 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
1873 return -1;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02001874 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 }
1876 else if (!strcmp(args[0], "server")) { /* server address */
1877 int cur_arg;
1878 char *rport;
1879 char *raddr;
1880 short realport;
1881 int do_check;
1882
1883 if (curproxy == &defproxy) {
1884 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1885 return -1;
1886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1888 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889
1890 if (!*args[2]) {
1891 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1892 file, linenum, args[0]);
1893 return -1;
1894 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001895
1896 err = invalid_char(args[1]);
1897 if (err) {
1898 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1899 file, linenum, *err, args[1]);
1900 return -1;
1901 }
1902
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
1904 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1905 return -1;
1906 }
1907
1908 /* the servers are linked backwards first */
1909 newsrv->next = curproxy->srv;
1910 curproxy->srv = newsrv;
1911 newsrv->proxy = curproxy;
Willy Tarreaudcd47712007-11-04 23:35:08 +01001912 newsrv->puid = curproxy->next_svid++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913
1914 LIST_INIT(&newsrv->pendconns);
1915 do_check = 0;
1916 newsrv->state = SRV_RUNNING; /* early server setup */
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001917 newsrv->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 newsrv->id = strdup(args[1]);
1919
1920 /* several ways to check the port component :
1921 * - IP => port=+0, relative
1922 * - IP: => port=+0, relative
1923 * - IP:N => port=N, absolute
1924 * - IP:+N => port=+N, relative
1925 * - IP:-N => port=-N, relative
1926 */
1927 raddr = strdup(args[2]);
1928 rport = strchr(raddr, ':');
1929 if (rport) {
1930 *rport++ = 0;
1931 realport = atol(rport);
Willy Tarreau8f8e6452007-06-17 21:51:38 +02001932 if (!isdigit((unsigned char)*rport))
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 newsrv->state |= SRV_MAPPORTS;
1934 } else {
1935 realport = 0;
1936 newsrv->state |= SRV_MAPPORTS;
1937 }
1938
1939 newsrv->addr = *str2sa(raddr);
1940 newsrv->addr.sin_port = htons(realport);
1941 free(raddr);
1942
1943 newsrv->curfd = -1; /* no health-check in progress */
1944 newsrv->inter = DEF_CHKINTR;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001945 newsrv->fastinter = 0; /* 0 => use newsrv->inter instead */
1946 newsrv->downinter = 0; /* 0 => use newsrv->inter instead */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 newsrv->rise = DEF_RISETIME;
1948 newsrv->fall = DEF_FALLTIME;
1949 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreau417fae02007-03-25 21:16:40 +02001950 newsrv->uweight = 1;
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02001951 newsrv->maxqueue = 0;
Willy Tarreau9909fc12007-11-30 17:42:05 +01001952 newsrv->slowstart = 0;
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02001953
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 cur_arg = 3;
1955 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956 if (!strcmp(args[cur_arg], "id")) {
1957 struct server *target;
1958
1959 if (!*args[cur_arg + 1]) {
1960 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1961 file, linenum, args[cur_arg]);
1962 return -1;
1963 }
1964
1965 newsrv->puid = atol(args[cur_arg + 1]);
1966
1967 if (newsrv->puid< 1001) {
1968 Alert("parsing [%s:%d]: custom id has to be > 1000",
1969 file, linenum);
1970 return -1;
1971 }
1972
1973 for (target = proxy->srv; target; target = target->next)
1974 if (newsrv != target && newsrv->puid == target->puid) {
1975 Alert("parsing [%s:%d]: custom id has to be unique but is duplicated in %s and %s.\n",
1976 file, linenum, newsrv->id, target->id);
1977 return -1;
1978 }
1979 cur_arg += 2;
1980 }
1981 else if (!strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 newsrv->cookie = strdup(args[cur_arg + 1]);
1983 newsrv->cklen = strlen(args[cur_arg + 1]);
1984 cur_arg += 2;
1985 }
Willy Tarreau21d2af32008-02-14 20:25:24 +01001986 else if (!strcmp(args[cur_arg], "redir")) {
1987 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
1988 newsrv->rdr_len = strlen(args[cur_arg + 1]);
1989 cur_arg += 2;
1990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 else if (!strcmp(args[cur_arg], "rise")) {
1992 newsrv->rise = atol(args[cur_arg + 1]);
1993 newsrv->health = newsrv->rise;
1994 cur_arg += 2;
1995 }
1996 else if (!strcmp(args[cur_arg], "fall")) {
1997 newsrv->fall = atol(args[cur_arg + 1]);
1998 cur_arg += 2;
1999 }
2000 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002001 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2002 if (err) {
2003 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
2004 file, linenum, *err, newsrv->id);
2005 return -1;
2006 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002007 if (val <= 0) {
2008 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2009 file, linenum, val, args[cur_arg], newsrv->id);
2010 return -1;
2011 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002012 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 cur_arg += 2;
2014 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002015 else if (!strcmp(args[cur_arg], "fastinter")) {
2016 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2017 if (err) {
2018 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
2019 file, linenum, *err, newsrv->id);
2020 return -1;
2021 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002022 if (val <= 0) {
2023 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2024 file, linenum, val, args[cur_arg], newsrv->id);
2025 return -1;
2026 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002027 newsrv->fastinter = val;
2028 cur_arg += 2;
2029 }
2030 else if (!strcmp(args[cur_arg], "downinter")) {
2031 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
2032 if (err) {
2033 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
2034 file, linenum, *err, newsrv->id);
2035 return -1;
2036 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002037 if (val <= 0) {
2038 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2039 file, linenum, val, args[cur_arg], newsrv->id);
2040 return -1;
2041 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002042 newsrv->downinter = val;
2043 cur_arg += 2;
2044 }
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002045 else if (!strcmp(args[cur_arg], "addr")) {
2046 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02002047 cur_arg += 2;
2048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 else if (!strcmp(args[cur_arg], "port")) {
2050 newsrv->check_port = atol(args[cur_arg + 1]);
2051 cur_arg += 2;
2052 }
2053 else if (!strcmp(args[cur_arg], "backup")) {
2054 newsrv->state |= SRV_BACKUP;
2055 cur_arg ++;
2056 }
2057 else if (!strcmp(args[cur_arg], "weight")) {
2058 int w;
2059 w = atol(args[cur_arg + 1]);
2060 if (w < 1 || w > 256) {
2061 Alert("parsing [%s:%d] : weight of server %s is not within 1 and 256 (%d).\n",
2062 file, linenum, newsrv->id, w);
2063 return -1;
2064 }
Willy Tarreau417fae02007-03-25 21:16:40 +02002065 newsrv->uweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 cur_arg += 2;
2067 }
2068 else if (!strcmp(args[cur_arg], "minconn")) {
2069 newsrv->minconn = atol(args[cur_arg + 1]);
2070 cur_arg += 2;
2071 }
2072 else if (!strcmp(args[cur_arg], "maxconn")) {
2073 newsrv->maxconn = atol(args[cur_arg + 1]);
2074 cur_arg += 2;
2075 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02002076 else if (!strcmp(args[cur_arg], "maxqueue")) {
2077 newsrv->maxqueue = atol(args[cur_arg + 1]);
2078 cur_arg += 2;
2079 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01002080 else if (!strcmp(args[cur_arg], "slowstart")) {
2081 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01002082 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002083 if (err) {
2084 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
2085 file, linenum, *err, newsrv->id);
2086 return -1;
2087 }
Willy Tarreaue3838802009-03-21 18:58:32 +01002088 if (val <= 0) {
2089 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
2090 file, linenum, val, args[cur_arg], newsrv->id);
2091 return -1;
2092 }
Willy Tarreau3259e332007-12-03 01:51:45 +01002093 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01002094 cur_arg += 2;
2095 }
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002096 else if (!strcmp(args[cur_arg], "track")) {
2097
2098 if (!*args[cur_arg + 1]) {
2099 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
2100 file, linenum);
2101 return -1;
2102 }
2103
2104 newsrv->trackit = strdup(args[cur_arg + 1]);
2105
2106 cur_arg += 2;
2107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 else if (!strcmp(args[cur_arg], "check")) {
2109 global.maxsock++;
2110 do_check = 1;
2111 cur_arg += 1;
2112 }
2113 else if (!strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
2114 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002115#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002116 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optional '%s' <addr> as argument.\n",
2117 file, linenum, "source", "usesrc");
2118#else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>] as argument.\n",
2120 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002121#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 return -1;
2123 }
2124 newsrv->state |= SRV_BIND_SRC;
2125 newsrv->source_addr = *str2sa(args[cur_arg + 1]);
2126 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002127 while (*(args[cur_arg])) {
2128 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002129#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2130#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002131 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
2132 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
2133 file, linenum, "usesrc", "source");
2134 return -1;
2135 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002136#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002137 if (!*args[cur_arg + 1]) {
2138 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2139 file, linenum, "usesrc");
2140 return -1;
2141 }
2142 if (!strcmp(args[cur_arg + 1], "client")) {
2143 newsrv->state |= SRV_TPROXY_CLI;
2144 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2145 newsrv->state |= SRV_TPROXY_CIP;
2146 } else {
2147 newsrv->state |= SRV_TPROXY_ADDR;
2148 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
2149 }
2150 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002151#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01002152 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002153#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002154 cur_arg += 2;
2155 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002156#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01002157 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002158 file, linenum, "usesrc");
2159 return -1;
Willy Tarreauc76721d2009-02-04 20:20:58 +01002160#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
2161 } /* "usesrc" */
2162
2163 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2164#ifdef SO_BINDTODEVICE
2165 if (!*args[cur_arg + 1]) {
2166 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2167 file, linenum, args[0]);
2168 return -1;
2169 }
2170 if (newsrv->iface_name)
2171 free(newsrv->iface_name);
2172
2173 newsrv->iface_name = strdup(args[cur_arg + 1]);
2174 newsrv->iface_len = strlen(newsrv->iface_name);
2175 global.last_checks |= LSTCHK_NETADM;
2176#else
2177 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2178 file, linenum, args[0], args[cur_arg]);
2179 return -1;
Willy Tarreau77074d52006-11-12 23:57:19 +01002180#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01002181 cur_arg += 2;
2182 continue;
2183 }
2184 /* this keyword in not an option of "source" */
2185 break;
2186 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002188 else if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
2189 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2190 file, linenum, "usesrc", "source");
2191 return -1;
2192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 else {
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002194 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 +02002195 file, linenum, newsrv->id);
2196 return -1;
2197 }
2198 }
2199
2200 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01002201 if (newsrv->trackit) {
2202 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
2203 file, linenum);
2204 return -1;
2205 }
2206
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002207 if (!newsrv->check_port && newsrv->check_addr.sin_port)
2208 newsrv->check_port = newsrv->check_addr.sin_port;
2209
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
2211 newsrv->check_port = realport; /* by default */
2212 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01002213 /* not yet valid, because no port was set on
2214 * the server either. We'll check if we have
2215 * a known port on the first listener.
2216 */
2217 struct listener *l;
2218 l = curproxy->listen;
2219 if (l) {
2220 int port;
2221 port = (l->addr.ss_family == AF_INET6)
2222 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
2223 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
2224 newsrv->check_port = port;
2225 }
2226 }
2227 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
2229 file, linenum, newsrv->id);
2230 return -1;
2231 }
2232 newsrv->state |= SRV_CHECKED;
2233 }
2234
2235 if (newsrv->state & SRV_BACKUP)
2236 curproxy->srv_bck++;
2237 else
2238 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01002239
2240 newsrv->prev_state = newsrv->state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01002243 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 int facility;
2245
2246 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
2247 curproxy->logfac1 = global.logfac1;
2248 curproxy->logsrv1 = global.logsrv1;
2249 curproxy->loglev1 = global.loglev1;
2250 curproxy->logfac2 = global.logfac2;
2251 curproxy->logsrv2 = global.logsrv2;
2252 curproxy->loglev2 = global.loglev2;
2253 }
2254 else if (*(args[1]) && *(args[2])) {
2255 int level;
2256
2257 facility = get_log_facility(args[2]);
2258 if (facility < 0) {
2259 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
2260 exit(1);
2261 }
2262
2263 level = 7; /* max syslog level = debug */
2264 if (*(args[3])) {
2265 level = get_log_level(args[3]);
2266 if (level < 0) {
2267 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
2268 exit(1);
2269 }
2270 }
2271
Robert Tsai81ae1952007-12-05 10:47:29 +01002272 if (args[1][0] == '/') {
2273 logsrv.u.addr.sa_family = AF_UNIX;
2274 logsrv.u.un = *str2sun(args[1]);
2275 } else {
2276 logsrv.u.addr.sa_family = AF_INET;
2277 logsrv.u.in = *str2sa(args[1]);
2278 if (!logsrv.u.in.sin_port) {
2279 logsrv.u.in.sin_port =
2280 htons(SYSLOG_PORT);
2281 }
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283
2284 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002285 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 curproxy->logfac1 = facility;
2287 curproxy->loglev1 = level;
2288 }
2289 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01002290 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 curproxy->logfac2 = facility;
2292 curproxy->loglev2 = level;
2293 }
2294 else {
2295 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
2296 return -1;
2297 }
2298 }
2299 else {
2300 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
2301 file, linenum);
2302 return -1;
2303 }
2304 }
2305 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002306 int cur_arg;
2307
Willy Tarreau977b8e42006-12-29 14:19:17 +01002308 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2309 return 0;
2310
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002312 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2313 file, linenum, "source", "usesrc", "interface");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 return -1;
2315 }
Willy Tarreau368480c2009-03-01 08:27:21 +01002316
2317 /* we must first clear any optional default setting */
2318 curproxy->options &= ~PR_O_TPXY_MASK;
2319 free(curproxy->iface_name);
2320 curproxy->iface_name = NULL;
2321 curproxy->iface_len = 0;
2322
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 curproxy->source_addr = *str2sa(args[1]);
2324 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002325
2326 cur_arg = 2;
2327 while (*(args[cur_arg])) {
2328 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002329#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
2330#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002331 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
2332 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
2333 file, linenum, "usesrc");
2334 return -1;
2335 }
2336#endif
2337 if (!*args[cur_arg + 1]) {
2338 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2339 file, linenum, "usesrc");
2340 return -1;
2341 }
2342
2343 if (!strcmp(args[cur_arg + 1], "client")) {
2344 curproxy->options |= PR_O_TPXY_CLI;
2345 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2346 curproxy->options |= PR_O_TPXY_CIP;
2347 } else {
2348 curproxy->options |= PR_O_TPXY_ADDR;
2349 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
2350 }
2351 global.last_checks |= LSTCHK_NETADM;
2352#if !defined(CONFIG_HAP_LINUX_TPROXY)
2353 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002354#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002355#else /* no TPROXY support */
2356 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01002357 file, linenum, "usesrc");
2358 return -1;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002359#endif
2360 cur_arg += 2;
2361 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01002362 }
2363
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002364 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2365#ifdef SO_BINDTODEVICE
2366 if (!*args[cur_arg + 1]) {
2367 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
2368 file, linenum, args[0]);
2369 return -1;
2370 }
2371 if (curproxy->iface_name)
2372 free(curproxy->iface_name);
2373
2374 curproxy->iface_name = strdup(args[cur_arg + 1]);
2375 curproxy->iface_len = strlen(curproxy->iface_name);
2376 global.last_checks |= LSTCHK_NETADM;
2377#else
2378 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2379 file, linenum, args[0], args[cur_arg]);
2380 return -1;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01002381#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002382 cur_arg += 2;
2383 continue;
2384 }
2385 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
2386 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002387 return -1;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01002390 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
2391 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
2392 file, linenum, "usesrc", "source");
2393 return -1;
2394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
2396 regex_t *preg;
2397 if (curproxy == &defproxy) {
2398 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2399 return -1;
2400 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002401 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2402 return 0;
2403
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 if (*(args[1]) == 0 || *(args[2]) == 0) {
2405 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2406 file, linenum, args[0]);
2407 return -1;
2408 }
2409
2410 preg = calloc(1, sizeof(regex_t));
2411 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2412 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2413 return -1;
2414 }
2415
2416 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2417 if (err) {
2418 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2419 file, linenum, *err);
2420 return -1;
2421 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002422 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 }
2424 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
2425 regex_t *preg;
2426 if (curproxy == &defproxy) {
2427 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2428 return -1;
2429 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2431 return 0;
2432
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 if (*(args[1]) == 0) {
2434 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2435 return -1;
2436 }
2437
2438 preg = calloc(1, sizeof(regex_t));
2439 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2440 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2441 return -1;
2442 }
2443
2444 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002445 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 }
2447 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
2448 regex_t *preg;
2449 if (curproxy == &defproxy) {
2450 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2451 return -1;
2452 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2454 return 0;
2455
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 if (*(args[1]) == 0) {
2457 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2458 return -1;
2459 }
2460
2461 preg = calloc(1, sizeof(regex_t));
2462 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2463 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2464 return -1;
2465 }
2466
2467 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002468 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
2471 regex_t *preg;
2472 if (curproxy == &defproxy) {
2473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2474 return -1;
2475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2477 return 0;
2478
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 if (*(args[1]) == 0) {
2480 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2481 return -1;
2482 }
2483
2484 preg = calloc(1, sizeof(regex_t));
2485 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2486 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2487 return -1;
2488 }
2489
2490 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002491 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002492 }
2493 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
2494 regex_t *preg;
2495 if (curproxy == &defproxy) {
2496 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2497 return -1;
2498 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2500 return 0;
2501
Willy Tarreaubaaee002006-06-26 02:48:02 +02002502 if (*(args[1]) == 0) {
2503 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2504 return -1;
2505 }
2506
2507 preg = calloc(1, sizeof(regex_t));
2508 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2509 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2510 return -1;
2511 }
2512
2513 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002514 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002516 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
2517 regex_t *preg;
2518 if (curproxy == &defproxy) {
2519 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2520 return -1;
2521 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002522 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2523 return 0;
2524
Willy Tarreaub8750a82006-09-03 09:56:00 +02002525 if (*(args[1]) == 0) {
2526 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2527 return -1;
2528 }
2529
2530 preg = calloc(1, sizeof(regex_t));
2531 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2532 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2533 return -1;
2534 }
2535
2536 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002537 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002538 }
Willy Tarreaua496b602006-12-17 23:15:24 +01002539 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
2540 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002541 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2543 return -1;
2544 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2546 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002547
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002549 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2550 file, linenum, args[0]);
2551 return -1;
2552 }
2553
2554 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002556 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2557 }
2558
2559 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002560 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002561 }
2562 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
2563 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002565 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2566 return -1;
2567 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002568 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2569 return 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01002570
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002572 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
2573 file, linenum, args[0]);
2574 return -1;
2575 }
2576
2577 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01002579 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2580 }
2581
2582 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02002583 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01002584 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
2586 regex_t *preg;
2587 if (curproxy == &defproxy) {
2588 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2589 return -1;
2590 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002591 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2592 return 0;
2593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 if (*(args[1]) == 0 || *(args[2]) == 0) {
2595 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2596 file, linenum, args[0]);
2597 return -1;
2598 }
2599
2600 preg = calloc(1, sizeof(regex_t));
2601 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2602 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2603 return -1;
2604 }
2605
2606 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
2607 if (err) {
2608 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2609 file, linenum, *err);
2610 return -1;
2611 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002612 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 }
2614 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
2615 regex_t *preg;
2616 if (curproxy == &defproxy) {
2617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2618 return -1;
2619 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2621 return 0;
2622
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 if (*(args[1]) == 0) {
2624 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2625 return -1;
2626 }
2627
2628 preg = calloc(1, sizeof(regex_t));
2629 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2630 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2631 return -1;
2632 }
2633
2634 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002635 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
2637 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
2638 regex_t *preg;
2639 if (curproxy == &defproxy) {
2640 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2641 return -1;
2642 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002643 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2644 return 0;
2645
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 if (*(args[1]) == 0) {
2647 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2648 return -1;
2649 }
2650
2651 preg = calloc(1, sizeof(regex_t));
2652 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2653 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2654 return -1;
2655 }
2656
2657 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002658 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 }
2660 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
2661 regex_t *preg;
2662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 return -1;
2665 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002666 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2667 return 0;
2668
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 if (*(args[1]) == 0) {
2670 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2671 return -1;
2672 }
2673
2674 preg = calloc(1, sizeof(regex_t));
2675 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2676 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2677 return -1;
2678 }
2679
2680 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002681 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 }
2683 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
2684 regex_t *preg;
2685 if (curproxy == &defproxy) {
2686 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2687 return -1;
2688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002689 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2690 return 0;
2691
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 if (*(args[1]) == 0) {
2693 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2694 return -1;
2695 }
2696
2697 preg = calloc(1, sizeof(regex_t));
2698 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2699 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2700 return -1;
2701 }
2702
2703 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002704 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02002706 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
2707 regex_t *preg;
2708 if (curproxy == &defproxy) {
2709 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2710 return -1;
2711 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002712 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2713 return 0;
2714
Willy Tarreaub8750a82006-09-03 09:56:00 +02002715 if (*(args[1]) == 0) {
2716 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
2717 return -1;
2718 }
2719
2720 preg = calloc(1, sizeof(regex_t));
2721 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2722 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2723 return -1;
2724 }
2725
2726 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02002727 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02002728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 else if (!strcmp(args[0], "reqadd")) { /* add request header */
2730 if (curproxy == &defproxy) {
2731 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2732 return -1;
2733 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2735 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736
2737 if (curproxy->nb_reqadd >= MAX_NEWHDR) {
2738 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2739 return 0;
2740 }
2741
2742 if (*(args[1]) == 0) {
2743 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2744 return -1;
2745 }
2746
2747 curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]);
Willy Tarreau61d18892009-03-31 10:49:21 +02002748 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 }
2750 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
2751 regex_t *preg;
2752
2753 if (*(args[1]) == 0 || *(args[2]) == 0) {
2754 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2755 file, linenum, args[0]);
2756 return -1;
2757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002758 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2759 return 0;
2760
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 preg = calloc(1, sizeof(regex_t));
2762 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2763 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2764 return -1;
2765 }
2766
2767 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2768 if (err) {
2769 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2770 file, linenum, *err);
2771 return -1;
2772 }
Willy Tarreau61d18892009-03-31 10:49:21 +02002773 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 }
2775 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
2776 regex_t *preg;
2777 if (curproxy == &defproxy) {
2778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2779 return -1;
2780 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002781 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2782 return 0;
2783
Willy Tarreaubaaee002006-06-26 02:48:02 +02002784 if (*(args[1]) == 0) {
2785 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2786 return -1;
2787 }
2788
2789 preg = calloc(1, sizeof(regex_t));
2790 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2791 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2792 return -1;
2793 }
2794
2795 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2796 if (err) {
2797 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2798 file, linenum, *err);
2799 return -1;
2800 }
2801 }
2802 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
2803 regex_t *preg;
2804 if (curproxy == &defproxy) {
2805 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2806 return -1;
2807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002808 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2809 return 0;
2810
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 if (*(args[1]) == 0) {
2812 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2813 return -1;
2814 }
2815
2816 preg = calloc(1, sizeof(regex_t));
2817 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
2818 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2819 return -1;
2820 }
2821
2822 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2823 if (err) {
2824 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2825 file, linenum, *err);
2826 return -1;
2827 }
2828 }
2829 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
2830 regex_t *preg;
2831 if (curproxy == &defproxy) {
2832 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2833 return -1;
2834 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002835 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2836 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837
2838 if (*(args[1]) == 0 || *(args[2]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
2840 file, linenum, args[0]);
2841 return -1;
2842 }
2843
2844 preg = calloc(1, sizeof(regex_t));
2845 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2846 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2847 return -1;
2848 }
2849
2850 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
2851 if (err) {
2852 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2853 file, linenum, *err);
2854 return -1;
2855 }
2856 }
2857 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
2858 regex_t *preg;
2859 if (curproxy == &defproxy) {
2860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2861 return -1;
2862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2864 return 0;
2865
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 if (*(args[1]) == 0) {
2867 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2868 return -1;
2869 }
2870
2871 preg = calloc(1, sizeof(regex_t));
2872 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2873 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2874 return -1;
2875 }
2876
2877 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
2878 if (err) {
2879 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2880 file, linenum, *err);
2881 return -1;
2882 }
2883 }
2884 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
2885 regex_t *preg;
2886 if (curproxy == &defproxy) {
2887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2888 return -1;
2889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002890 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2891 return 0;
2892
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893 if (*(args[1]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
2895 return -1;
2896 }
2897
2898 preg = calloc(1, sizeof(regex_t));
2899 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
2900 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
2901 return -1;
2902 }
2903
2904 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
2905 if (err) {
2906 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
2907 file, linenum, *err);
2908 return -1;
2909 }
2910 }
2911 else if (!strcmp(args[0], "rspadd")) { /* add response header */
2912 if (curproxy == &defproxy) {
2913 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2914 return -1;
2915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002916 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
2917 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918
2919 if (curproxy->nb_rspadd >= MAX_NEWHDR) {
2920 Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
2921 return 0;
2922 }
2923
2924 if (*(args[1]) == 0) {
2925 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
2926 return -1;
2927 }
2928
2929 curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]);
2930 }
2931 else if (!strcmp(args[0], "errorloc") ||
2932 !strcmp(args[0], "errorloc302") ||
2933 !strcmp(args[0], "errorloc303")) { /* error location */
2934 int errnum, errlen;
2935 char *err;
2936
Willy Tarreau977b8e42006-12-29 14:19:17 +01002937 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2938 return 0;
2939
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02002941 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 return -1;
2943 }
2944
2945 errnum = atol(args[1]);
2946 if (!strcmp(args[0], "errorloc303")) {
2947 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
2948 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
2949 } else {
2950 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
2951 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
2952 }
2953
Willy Tarreau0f772532006-12-23 20:51:41 +01002954 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
2955 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002956 free(curproxy->errmsg[rc].str);
Willy Tarreau0f772532006-12-23 20:51:41 +01002957 curproxy->errmsg[rc].str = err;
2958 curproxy->errmsg[rc].len = errlen;
2959 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002962
2963 if (rc >= HTTP_ERR_SIZE) {
2964 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
2965 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 free(err);
2967 }
2968 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02002969 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
2970 int errnum, errlen, fd;
2971 char *err;
2972 struct stat stat;
2973
2974 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
2975 return 0;
2976
2977 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02002978 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau3f49b302007-06-11 00:29:26 +02002979 return -1;
2980 }
2981
2982 fd = open(args[2], O_RDONLY);
2983 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
2984 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
2985 file, linenum, args[2], args[1]);
2986 if (fd >= 0)
2987 close(fd);
2988 return -1;
2989 }
2990
2991 if (stat.st_size <= BUFSIZE) {
2992 errlen = stat.st_size;
2993 } else {
2994 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
2995 file, linenum, args[2], BUFSIZE);
2996 errlen = BUFSIZE;
2997 }
2998
2999 err = malloc(errlen); /* malloc() must succeed during parsing */
3000 errnum = read(fd, err, errlen);
3001 if (errnum != errlen) {
3002 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
3003 file, linenum, args[2], args[1]);
3004 close(fd);
3005 free(err);
3006 return -1;
3007 }
3008 close(fd);
3009
3010 errnum = atol(args[1]);
3011 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
3012 if (http_err_codes[rc] == errnum) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02003013 free(curproxy->errmsg[rc].str);
Willy Tarreau3f49b302007-06-11 00:29:26 +02003014 curproxy->errmsg[rc].str = err;
3015 curproxy->errmsg[rc].len = errlen;
3016 break;
3017 }
3018 }
3019
3020 if (rc >= HTTP_ERR_SIZE) {
3021 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
3022 file, linenum, errnum);
3023 free(err);
3024 }
3025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003027 struct cfg_kw_list *kwl;
3028 int index;
3029
3030 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3031 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3032 if (kwl->kw[index].section != CFG_LISTEN)
3033 continue;
3034 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3035 /* prepare error message just in case */
3036 snprintf(trash, sizeof(trash),
3037 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02003038 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
3039 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003040 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
3041 return -1;
3042 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02003043 else if (rc > 0) {
3044 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
3045 return 0;
3046 }
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003047 return 0;
3048 }
3049 }
3050 }
3051
Willy Tarreau6daf3432008-01-22 16:44:08 +01003052 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 return -1;
3054 }
3055 return 0;
3056}
3057
3058
3059/*
3060 * This function reads and parses the configuration file given in the argument.
3061 * returns 0 if OK, -1 if error.
3062 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02003063int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003065 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 FILE *f;
3067 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 int cfgerr = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 int confsect = CFG_NONE;
3070
3071 struct proxy *curproxy = NULL;
3072 struct server *newsrv = NULL;
3073
3074 if ((f=fopen(file,"r")) == NULL)
3075 return -1;
3076
3077 init_default_instance();
3078
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003079 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003080 int arg, inv = 0 ;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003081 char *end;
3082 char *args[MAX_LINE_ARGS + 1];
3083 char *line = thisline;
3084
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 linenum++;
3086
3087 end = line + strlen(line);
3088
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003089 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3090 /* Check if we reached the limit and the last char is not \n.
3091 * Watch out for the last line without the terminating '\n'!
3092 */
3093 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
3094 file, linenum, sizeof(thisline)-1);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003095 goto err;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003096 }
3097
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003099 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 line++;
3101
3102 arg = 0;
3103 args[arg] = line;
3104
3105 while (*line && arg < MAX_LINE_ARGS) {
3106 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
3107 * C equivalent value. Other combinations left unchanged (eg: \1).
3108 */
3109 if (*line == '\\') {
3110 int skip = 0;
3111 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
3112 *line = line[1];
3113 skip = 1;
3114 }
3115 else if (line[1] == 'r') {
3116 *line = '\r';
3117 skip = 1;
3118 }
3119 else if (line[1] == 'n') {
3120 *line = '\n';
3121 skip = 1;
3122 }
3123 else if (line[1] == 't') {
3124 *line = '\t';
3125 skip = 1;
3126 }
3127 else if (line[1] == 'x') {
3128 if ((line + 3 < end ) && ishex(line[2]) && ishex(line[3])) {
3129 unsigned char hex1, hex2;
3130 hex1 = toupper(line[2]) - '0';
3131 hex2 = toupper(line[3]) - '0';
3132 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
3133 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
3134 *line = (hex1<<4) + hex2;
3135 skip = 3;
3136 }
3137 else {
3138 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003139 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 }
3141 }
3142 if (skip) {
3143 memmove(line + 1, line + 1 + skip, end - (line + skip + 1));
3144 end -= skip;
3145 }
3146 line++;
3147 }
3148 else if (*line == '#' || *line == '\n' || *line == '\r') {
3149 /* end of string, end of loop */
3150 *line = 0;
3151 break;
3152 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003153 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01003155 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02003156 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 line++;
3158 args[++arg] = line;
3159 }
3160 else {
3161 line++;
3162 }
3163 }
3164
3165 /* empty line */
3166 if (!**args)
3167 continue;
3168
Willy Tarreau540abe42007-05-02 20:50:16 +02003169 /* zero out remaining args and ensure that at least one entry
3170 * is zeroed out.
3171 */
3172 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 args[arg] = line;
3174 }
3175
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003176 if (!strcmp(args[0], "no")) {
3177 inv = 1;
3178 for (arg=0; *args[arg+1]; arg++)
3179 args[arg] = args[arg+1]; // shift args after inversion
3180 }
3181
3182 if (inv && strcmp(args[0], "option")) {
3183 Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003184 goto err;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003185 }
3186
Willy Tarreau977b8e42006-12-29 14:19:17 +01003187 if (!strcmp(args[0], "listen") ||
3188 !strcmp(args[0], "frontend") ||
3189 !strcmp(args[0], "backend") ||
3190 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01003191 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003193 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003194 cursection = strdup(args[0]);
3195 }
3196 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003198 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003199 cursection = strdup(args[0]);
3200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 /* else it's a section keyword */
3202
3203 switch (confsect) {
3204 case CFG_LISTEN:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003205 if (cfg_parse_listen(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003206 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 break;
3208 case CFG_GLOBAL:
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003209 if (cfg_parse_global(file, linenum, args, inv) < 0)
Willy Tarreau6daf3432008-01-22 16:44:08 +01003210 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 break;
3212 default:
3213 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003214 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003217 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003218 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 fclose(f);
3220
3221 /*
3222 * Now, check for the integrity of all that we have collected.
3223 */
3224
3225 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02003226 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227
Willy Tarreau55bc0f82009-03-15 14:51:53 +01003228 /* first, we will invert the proxy list order */
3229 curproxy = NULL;
3230 while (proxy) {
3231 struct proxy *next;
3232
3233 next = proxy->next;
3234 proxy->next = curproxy;
3235 curproxy = proxy;
3236 if (!next)
3237 break;
3238 proxy = next;
3239 }
3240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 if ((curproxy = proxy) == NULL) {
3242 Alert("parsing %s : no <listen> line. Nothing to do !\n",
3243 file);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003244 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
3246
3247 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003248 struct switching_rule *rule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003249 struct listener *listener;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003250
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02003252 /* ensure we don't keep listeners uselessly bound */
3253 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 curproxy = curproxy->next;
3255 continue;
3256 }
3257
Willy Tarreauff01a212009-03-15 13:46:16 +01003258 switch (curproxy->mode) {
3259 case PR_MODE_HEALTH:
3260 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3261 if (!(curproxy->cap & PR_CAP_FE)) {
3262 Alert("parsing %s : %s '%s' cannot be in health mode as it has no frontend capability.\n",
3263 file, proxy_type_str(curproxy), curproxy->id);
3264 cfgerr++;
3265 }
3266
3267 if (curproxy->srv != NULL)
3268 Warning("parsing %s : servers will be ignored for %s '%s'.\n",
3269 file, proxy_type_str(curproxy), curproxy->id);
3270 break;
3271
3272 case PR_MODE_TCP:
3273 cfgerr += proxy_cfg_ensure_no_http(curproxy, file);
3274 break;
3275
3276 case PR_MODE_HTTP:
3277 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
3278 Alert("parsing %s : HTTP proxy %s has a cookie but no server list !\n",
3279 file, curproxy->id);
3280 cfgerr++;
3281 }
3282 break;
3283 }
3284
3285 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286 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 +01003287 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 cfgerr++;
3289 }
Willy Tarreauff01a212009-03-15 13:46:16 +01003290
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003291 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
3292 if (curproxy->lbprm.algo & BE_LB_ALGO) {
3293 if (curproxy->options & PR_O_TRANSP) {
3294 Alert("parsing %s : %s '%s' cannot use both transparent and balance mode.\n",
3295 file, proxy_type_str(curproxy), curproxy->id);
3296 cfgerr++;
3297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003299 else if (curproxy->srv == NULL) {
3300 Alert("parsing %s : %s '%s' needs at least 1 server in balance mode.\n",
3301 file, proxy_type_str(curproxy), curproxy->id);
3302 cfgerr++;
3303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01003305 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
3306 Warning("parsing %s : dispatch address of %s '%s' will be ignored in balance mode.\n",
3307 file, proxy_type_str(curproxy), curproxy->id);
3308 }
3309 }
3310 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
3311 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
3312 /* If no LB algo is set in a backend, and we're not in
3313 * transparent mode, dispatch mode nor proxy mode, we
3314 * want to use balance roundrobin by default.
3315 */
3316 curproxy->lbprm.algo &= ~BE_LB_ALGO;
3317 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
3319 }
Willy Tarreau193cf932007-09-17 10:17:23 +02003320
Willy Tarreau82936582007-11-30 15:20:09 +01003321 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
3322 curproxy->options &= ~PR_O_DISABLE404;
3323 Warning("parsing %s : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
3324 file, "disable-on-404", proxy_type_str(curproxy), curproxy->id);
3325 }
3326
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003327 /* if a default backend was specified, let's find it */
3328 if (curproxy->defbe.name) {
3329 struct proxy *target;
3330
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003331 target = findproxy(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
3332 if (!target) {
3333 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
3334 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003335 cfgerr++;
3336 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003337 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
3338 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003339 } else {
3340 free(curproxy->defbe.name);
3341 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003342 /* we force the backend to be present on at least all of
3343 * the frontend's processes.
3344 */
3345 target->bind_proc = curproxy->bind_proc ?
3346 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 }
3348 }
3349
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003350 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01003351 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
3352 /* map jump target for ACT_SETBE in req_rep chain */
3353 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01003354 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003355 struct proxy *target;
3356
Willy Tarreaua496b602006-12-17 23:15:24 +01003357 if (exp->action != ACT_SETBE)
3358 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003359
3360 target = findproxy(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
3361 if (!target) {
3362 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
3363 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01003364 cfgerr++;
3365 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003366 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
3367 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01003368 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01003369 } else {
3370 free((void *)exp->replace);
3371 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003372 /* we force the backend to be present on at least all of
3373 * the frontend's processes.
3374 */
3375 target->bind_proc = curproxy->bind_proc ?
3376 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01003377 }
3378 }
3379 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003380
3381 /* find the target proxy for 'use_backend' rules */
3382 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003383 struct proxy *target;
3384
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003385 target = findproxy(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003386
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003387 if (!target) {
3388 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
3389 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003390 cfgerr++;
3391 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01003392 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
3393 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003394 cfgerr++;
3395 } else {
3396 free((void *)rule->be.name);
3397 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003398 /* we force the backend to be present on at least all of
3399 * the frontend's processes.
3400 */
3401 target->bind_proc = curproxy->bind_proc ?
3402 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003403 }
3404 }
3405
Willy Tarreau2738a142006-07-08 17:28:09 +02003406 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003407 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02003408 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003409 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003410 Warning("parsing %s : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02003411 " | While not properly invalid, you will certainly encounter various problems\n"
3412 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01003413 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +01003414 file, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau2738a142006-07-08 17:28:09 +02003415 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003416
Willy Tarreau1fa31262007-12-03 00:36:16 +01003417 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
3418 * We must still support older configurations, so let's find out whether those
3419 * parameters have been set or must be copied from contimeouts.
3420 */
3421 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003422 if (!curproxy->timeout.tarpit ||
3423 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003424 /* tarpit timeout not set. We search in the following order:
3425 * default.tarpit, curr.connect, default.connect.
3426 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003427 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003428 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003429 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003430 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003431 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003432 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003433 }
3434 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003435 (!curproxy->timeout.queue ||
3436 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01003437 /* queue timeout not set. We search in the following order:
3438 * default.queue, curr.connect, default.connect.
3439 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003440 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01003441 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003442 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003443 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003444 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003445 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01003446 }
3447 }
3448
Willy Tarreauf3c69202006-07-09 16:42:34 +02003449 if (curproxy->options & PR_O_SSL3_CHK) {
3450 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
3451 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
3452 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
3453 }
3454
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003455 /* The small pools required for the capture lists */
3456 if (curproxy->nb_req_cap)
3457 curproxy->req_cap_pool = create_pool("ptrcap",
3458 curproxy->nb_req_cap * sizeof(char *),
3459 MEM_F_SHARED);
3460 if (curproxy->nb_rsp_cap)
3461 curproxy->rsp_cap_pool = create_pool("ptrcap",
3462 curproxy->nb_rsp_cap * sizeof(char *),
3463 MEM_F_SHARED);
3464
Willy Tarreau1d4154a2007-05-13 22:57:02 +02003465 curproxy->hdr_idx_pool = create_pool("hdr_idx",
3466 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
3467 MEM_F_SHARED);
3468
Willy Tarreau86034312006-12-29 00:10:33 +01003469 /* for backwards compatibility with "listen" instances, if
3470 * fullconn is not set but maxconn is set, then maxconn
3471 * is used.
3472 */
3473 if (!curproxy->fullconn)
3474 curproxy->fullconn = curproxy->maxconn;
3475
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 /* first, we will invert the servers list order */
3477 newsrv = NULL;
3478 while (curproxy->srv) {
3479 struct server *next;
3480
3481 next = curproxy->srv->next;
3482 curproxy->srv->next = newsrv;
3483 newsrv = curproxy->srv;
3484 if (!next)
3485 break;
3486 curproxy->srv = next;
3487 }
3488
Willy Tarreau20697042007-11-15 23:26:18 +01003489 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01003490 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491
Willy Tarreaub625a082007-11-26 01:15:43 +01003492 /* round robin relies on a weight tree */
Willy Tarreau31682232007-11-29 15:38:04 +01003493 if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_RR)
Willy Tarreaub625a082007-11-26 01:15:43 +01003494 fwrr_init_server_groups(curproxy);
Willy Tarreau51406232008-03-10 22:04:20 +01003495 else if ((curproxy->lbprm.algo & BE_LB_ALGO) == BE_LB_ALGO_LC)
3496 fwlc_init_server_tree(curproxy);
Willy Tarreaub625a082007-11-26 01:15:43 +01003497 else
3498 init_server_map(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499
3500 if (curproxy->options & PR_O_LOGASAP)
3501 curproxy->to_log &= ~LW_BYTES;
3502
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01003504 * ensure that we're not cross-dressing a TCP server into HTTP.
3505 */
3506 newsrv = curproxy->srv;
3507 while (newsrv != NULL) {
3508 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003509 Alert("parsing [%s:%d] : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
3510 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau21d2af32008-02-14 20:25:24 +01003511 goto err;
3512 }
3513 newsrv = newsrv->next;
3514 }
3515
3516 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 * If this server supports a maxconn parameter, it needs a dedicated
3518 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003519 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 */
3521 newsrv = curproxy->srv;
3522 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01003523 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 /* Only 'minconn' was specified, or it was higher than or equal
3525 * to 'maxconn'. Let's turn this into maxconn and clean it, as
3526 * this will avoid further useless expensive computations.
3527 */
3528 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01003529 } else if (newsrv->maxconn && !newsrv->minconn) {
3530 /* minconn was not specified, so we set it to maxconn */
3531 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003532 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02003533 Alert("parsing [%s:%d] : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
3534 file, linenum, proxy_type_str(curproxy), curproxy->id);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003535 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003538 if (newsrv->trackit) {
3539 struct proxy *px;
3540 struct server *srv;
3541 char *pname, *sname;
3542
3543 pname = newsrv->trackit;
3544 sname = strrchr(pname, '/');
3545
3546 if (sname)
3547 *sname++ = '\0';
3548 else {
3549 sname = pname;
3550 pname = NULL;
3551 }
3552
3553 if (pname) {
3554 px = findproxy(pname, curproxy->mode, PR_CAP_BE);
3555 if (!px) {
3556 Alert("parsing %s, %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
3557 file, proxy_type_str(curproxy), curproxy->id,
3558 newsrv->id, pname);
3559 return -1;
3560 }
3561 } else
3562 px = curproxy;
3563
3564 srv = findserver(px, sname);
3565 if (!srv) {
3566 Alert("parsing %s, %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
3567 file, proxy_type_str(curproxy), curproxy->id,
3568 newsrv->id, sname);
3569 return -1;
3570 }
3571
3572 if (!(srv->state & SRV_CHECKED)) {
3573 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for "
3574 "tracing as it does not have checks enabled.\n",
3575 file, proxy_type_str(curproxy), curproxy->id,
3576 newsrv->id, px->id, srv->id);
3577 return -1;
3578 }
3579
3580 if (curproxy != px &&
3581 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
3582 Alert("parsing %s, %s '%s', server '%s': unable to use %s/%s for"
3583 "tracing: disable-on-404 option inconsistency.\n",
3584 file, proxy_type_str(curproxy), curproxy->id,
3585 newsrv->id, px->id, srv->id);
3586 return -1;
3587 }
3588
3589 newsrv->tracked = srv;
3590 newsrv->tracknext = srv->tracknext;
3591 srv->tracknext = newsrv;
3592
3593 free(newsrv->trackit);
3594 }
3595
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 newsrv = newsrv->next;
3597 }
3598
Willy Tarreaue6b98942007-10-29 01:09:36 +01003599 /* adjust this proxy's listeners */
3600 listener = curproxy->listen;
3601 while (listener) {
3602 if (curproxy->options & PR_O_TCP_NOLING)
3603 listener->options |= LI_O_NOLINGER;
3604 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003605 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01003606 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003607 listener->accept = event_accept;
3608 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01003609 listener->handler = process_session;
3610
3611 if (curproxy->mode == PR_MODE_HTTP)
3612 listener->analysers |= AN_REQ_HTTP_HDR;
3613
Willy Tarreaud869b242009-03-15 14:43:58 +01003614 if (curproxy->tcp_req.inspect_delay ||
3615 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreau3bc13772008-12-07 11:50:35 +01003616 listener->analysers |= AN_REQ_INSPECT;
Willy Tarreaue6b98942007-10-29 01:09:36 +01003617
3618 listener = listener->next;
3619 }
3620
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 curproxy = curproxy->next;
3622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003623
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 if (cfgerr > 0) {
3625 Alert("Errors found in configuration file, aborting.\n");
Willy Tarreau6daf3432008-01-22 16:44:08 +01003626 goto err;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003628
3629 /*
3630 * Recount currently required checks.
3631 */
3632
3633 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
3634 int optnum;
3635
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003636 for (optnum = 0; cfg_opts[optnum].name; optnum++)
3637 if (curproxy->options & cfg_opts[optnum].val)
3638 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003639
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003640 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
3641 if (curproxy->options2 & cfg_opts2[optnum].val)
3642 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003643 }
3644
Willy Tarreaua534fea2008-08-03 12:19:50 +02003645 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003646 cursection = NULL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003647 return 0;
Willy Tarreau6daf3432008-01-22 16:44:08 +01003648
3649 err:
Willy Tarreaua534fea2008-08-03 12:19:50 +02003650 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01003651 cursection = NULL;
3652 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653}
3654
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003655/*
3656 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
3657 * parsing sessions.
3658 */
3659void cfg_register_keywords(struct cfg_kw_list *kwl)
3660{
3661 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
3662}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663
Willy Tarreau5b2c3362008-07-09 19:39:06 +02003664/*
3665 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
3666 */
3667void cfg_unregister_keywords(struct cfg_kw_list *kwl)
3668{
3669 LIST_DEL(&kwl->list);
3670 LIST_INIT(&kwl->list);
3671}
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672
3673/*
3674 * Local variables:
3675 * c-indent-level: 8
3676 * c-basic-offset: 8
3677 * End:
3678 */