blob: 925013a35eb8d2016c838e32cf3aaafbefd718d2 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Emeric Brunaa35f1f2012-09-03 11:53:36 +020065#include <proto/shctx.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020067#ifdef USE_OPENSSL
68#include <proto/ssl_sock.h>
69#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020070#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010071#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072
73
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100195static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196{
197 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100198 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 int port, end;
200
201 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 while (next && *next) {
204 struct sockaddr_storage ss;
205
206 str = next;
207 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100208 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 *next++ = 0;
210 }
211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (*str == '/') {
213 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
214 /* so compute max path */
215 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
216 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Emeric Bruned760922010-10-22 17:59:25 +0200218 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100219 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
220 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200221 goto fail;
222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200225 ss.ss_family = AF_UNIX;
226 if (global.unix_bind.prefix) {
227 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
228 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
Emeric Bruned760922010-10-22 17:59:25 +0200230 else {
231 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
232 }
233 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 }
235 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 ss2 = str2sa_range(str, &port, &end);
239 if (!ss2) {
240 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
246 Alert("parsing [%s:%d] : missing port number: '%s'\n",
247 file, line, str);
248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 /* OK the address looks correct */
252 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
262 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 l->next = curproxy->listen;
270 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
272 l->fd = -1;
273 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200274 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 l->state = LI_INIT;
276
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100277 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100279 tcpv4_add_listener(l);
280 }
Emeric Bruned760922010-10-22 17:59:25 +0200281 else if (ss.ss_family == AF_INET6) {
282 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
283 tcpv6_add_listener(l);
284 }
285 else {
286 l->perm.ux.gid = l->perm.ux.uid = -1;
287 l->perm.ux.mode = 0;
288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
471 else if (!strcmp(args[0], "daemon")) {
472 global.mode |= MODE_DAEMON;
473 }
474 else if (!strcmp(args[0], "debug")) {
475 global.mode |= MODE_DEBUG;
476 }
477 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
483 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100489 else if (!strcmp(args[0], "nosplice")) {
490 global.tune.options &= ~GTUNE_USE_SPLICE;
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 else if (!strcmp(args[0], "quiet")) {
493 global.mode |= MODE_QUIET;
494 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 else if (!strcmp(args[0], "tune.maxpollevents")) {
496 if (global.tune.maxpollevents != 0) {
497 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 if (*(args[1]) == 0) {
502 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT | ERR_FATAL;
504 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200505 }
506 global.tune.maxpollevents = atol(args[1]);
507 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 else if (!strcmp(args[0], "tune.maxaccept")) {
509 if (global.tune.maxaccept != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100518 }
519 global.tune.maxaccept = atol(args[1]);
520 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200521 else if (!strcmp(args[0], "tune.chksize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.chksize = atol(args[1]);
528 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200529#ifdef USE_OPENSSL
530 else if (!strcmp(args[0], "tune.sslcachesize")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.sslcachesize = atol(args[1]);
537 }
538#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 else if (!strcmp(args[0], "tune.bufsize")) {
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.tune.bufsize = atol(args[1]);
546 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
547 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200548 trashlen = global.tune.bufsize;
549 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 }
551 else if (!strcmp(args[0], "tune.maxrewrite")) {
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.maxrewrite = atol(args[1]);
558 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
559 global.tune.maxrewrite = global.tune.bufsize / 2;
560 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100561 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
562 if (global.tune.client_rcvbuf != 0) {
563 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT;
565 goto out;
566 }
567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.client_rcvbuf = atol(args[1]);
573 }
574 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
575 if (global.tune.server_rcvbuf != 0) {
576 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.tune.server_rcvbuf = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "tune.sndbuf.client")) {
588 if (global.tune.client_sndbuf != 0) {
589 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT;
591 goto out;
592 }
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.client_sndbuf = atol(args[1]);
599 }
600 else if (!strcmp(args[0], "tune.sndbuf.server")) {
601 if (global.tune.server_sndbuf != 0) {
602 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT;
604 goto out;
605 }
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.server_sndbuf = atol(args[1]);
612 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200613 else if (!strcmp(args[0], "tune.pipesize")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.pipesize = atol(args[1]);
620 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200621 else if (!strcmp(args[0], "tune.http.maxhdr")) {
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.max_http_hdr = atol(args[1]);
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "uid")) {
630 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.uid = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "gid")) {
643 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.gid = atol(args[1]);
654 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 /* user/group name handling */
656 else if (!strcmp(args[0], "user")) {
657 struct passwd *ha_user;
658 if (global.uid != 0) {
659 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_user = getpwnam(args[1]);
665 if (ha_user != NULL) {
666 global.uid = (int)ha_user->pw_uid;
667 }
668 else {
669 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 else if (!strcmp(args[0], "group")) {
674 struct group *ha_group;
675 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200676 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 }
680 errno = 0;
681 ha_group = getgrnam(args[1]);
682 if (ha_group != NULL) {
683 global.gid = (int)ha_group->gr_gid;
684 }
685 else {
686 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200688 }
689 }
690 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 else if (!strcmp(args[0], "nbproc")) {
692 if (global.nbproc != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.nbproc = atol(args[1]);
703 }
704 else if (!strcmp(args[0], "maxconn")) {
705 if (global.maxconn != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 global.maxconn = atol(args[1]);
716#ifdef SYSTEM_MAXCONN
717 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
718 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);
719 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722#endif /* SYSTEM_MAXCONN */
723 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200724 else if (!strcmp(args[0], "maxsslconn")) {
725#ifdef USE_OPENSSL
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.maxsslconn = atol(args[1]);
732#else
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#endif
739 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200740 else if (!strcmp(args[0], "maxconnrate")) {
741 if (global.cps_lim != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT;
744 goto out;
745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.cps_lim = atol(args[1]);
752 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100753 else if (!strcmp(args[0], "maxpipes")) {
754 if (global.maxpipes != 0) {
755 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100763 }
764 global.maxpipes = atol(args[1]);
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "ulimit-n")) {
767 if (global.rlimit_nofile != 0) {
768 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 global.rlimit_nofile = atol(args[1]);
778 }
779 else if (!strcmp(args[0], "chroot")) {
780 if (global.chroot != NULL) {
781 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 global.chroot = strdup(args[1]);
791 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200792 else if (!strcmp(args[0], "description")) {
793 int i, len=0;
794 char *d;
795
796 if (!*args[1]) {
797 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802
803 for(i=1; *args[i]; i++)
804 len += strlen(args[i])+1;
805
806 if (global.desc)
807 free(global.desc);
808
809 global.desc = d = (char *)calloc(1, len);
810
811 d += sprintf(d, "%s", args[1]);
812 for(i=2; *args[i]; i++)
813 d += sprintf(d, " %s", args[i]);
814 }
815 else if (!strcmp(args[0], "node")) {
816 int i;
817 char c;
818
819 for (i=0; args[1][i]; i++) {
820 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100821 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
822 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200823 break;
824 }
825
826 if (!i || args[1][i]) {
827 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
828 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833
834 if (global.node)
835 free(global.node);
836
837 global.node = strdup(args[1]);
838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 else if (!strcmp(args[0], "pidfile")) {
840 if (global.pidfile != NULL) {
841 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.pidfile = strdup(args[1]);
851 }
Emeric Bruned760922010-10-22 17:59:25 +0200852 else if (!strcmp(args[0], "unix-bind")) {
853 int cur_arg = 1;
854 while (*(args[cur_arg])) {
855 if (!strcmp(args[cur_arg], "prefix")) {
856 if (global.unix_bind.prefix != NULL) {
857 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
858 err_code |= ERR_ALERT;
859 cur_arg += 2;
860 continue;
861 }
862
863 if (*(args[cur_arg+1]) == 0) {
864 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868 global.unix_bind.prefix = strdup(args[cur_arg+1]);
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "mode")) {
874
875 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
876 cur_arg += 2;
877 continue;
878 }
879
880 if (!strcmp(args[cur_arg], "uid")) {
881
882 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
883 cur_arg += 2;
884 continue;
885 }
886
887 if (!strcmp(args[cur_arg], "gid")) {
888
889 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "user")) {
895 struct passwd *user;
896
897 user = getpwnam(args[cur_arg + 1]);
898 if (!user) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
900 file, linenum, args[0], args[cur_arg + 1 ]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 global.unix_bind.ux.uid = user->pw_uid;
906 cur_arg += 2;
907 continue;
908 }
909
910 if (!strcmp(args[cur_arg], "group")) {
911 struct group *group;
912
913 group = getgrnam(args[cur_arg + 1]);
914 if (!group) {
915 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
916 file, linenum, args[0], args[cur_arg + 1 ]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920
921 global.unix_bind.ux.gid = group->gr_gid;
922 cur_arg += 2;
923 continue;
924 }
925
Willy Tarreaub48f9582011-09-05 01:17:06 +0200926 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
William Lallemand0f99e342011-10-12 17:50:54 +0200932 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
933 /* delete previous herited or defined syslog servers */
934 struct logsrv *back;
935 struct logsrv *tmp;
936
937 if (*(args[1]) != 0) {
938 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942
943 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
944 LIST_DEL(&tmp->list);
945 free(tmp);
946 }
947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200949 struct logsrv *logsrv;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[1]) == 0 || *(args[2]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
William Lallemand0f99e342011-10-12 17:50:54 +0200956
957 logsrv = calloc(1, sizeof(struct logsrv));
958
959 logsrv->facility = get_log_facility(args[2]);
960 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->level = get_log_level(args[3]);
969 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 }
975
William Lallemand0f99e342011-10-12 17:50:54 +0200976 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200978 logsrv->minlvl = get_log_level(args[4]);
979 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200982 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200983 }
984 }
985
Robert Tsai81ae1952007-12-05 10:47:29 +0100986 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 if (!sk) {
989 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100990 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100991 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200992 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100993 goto out;
994 }
William Lallemand0f99e342011-10-12 17:50:54 +0200995 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100996 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100997 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100998 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001001 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001002 goto out;
1003 }
William Lallemand0f99e342011-10-12 17:50:54 +02001004 logsrv->addr = *sk;
1005 if (!get_host_port(&logsrv->addr))
1006 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008
William Lallemand0f99e342011-10-12 17:50:54 +02001009 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001011 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1012 char *name;
1013 int len;
1014
1015 if (global.log_send_hostname != NULL) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT;
1018 goto out;
1019 }
1020
1021 if (*(args[1]))
1022 name = args[1];
1023 else
1024 name = hostname;
1025
1026 len = strlen(name);
1027
1028 /* We'll add a space after the name to respect the log format */
1029 free(global.log_send_hostname);
1030 global.log_send_hostname = malloc(len + 2);
1031 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1032 }
Kevinm48936af2010-12-22 16:08:21 +00001033 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 free(global.log_tag);
1040 global.log_tag = strdup(args[1]);
1041 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001042 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1043 if (global.spread_checks != 0) {
1044 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT;
1046 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001047 }
1048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001052 }
1053 global.spread_checks = atol(args[1]);
1054 if (global.spread_checks < 0 || global.spread_checks > 50) {
1055 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 struct cfg_kw_list *kwl;
1061 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001062 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001063
1064 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1065 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1066 if (kwl->kw[index].section != CFG_GLOBAL)
1067 continue;
1068 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1069 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001070 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001071 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001072 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001073 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001074 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001076 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001077 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001078 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_WARN;
1080 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001081 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001083 }
1084 }
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001090
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001092 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094}
1095
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001096void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001098 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 defproxy.mode = PR_MODE_TCP;
1100 defproxy.state = PR_STNEW;
1101 defproxy.maxconn = cfg_maxpconn;
1102 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001103
1104 defproxy.defsrv.inter = DEF_CHKINTR;
1105 defproxy.defsrv.fastinter = 0;
1106 defproxy.defsrv.downinter = 0;
1107 defproxy.defsrv.rise = DEF_RISETIME;
1108 defproxy.defsrv.fall = DEF_FALLTIME;
1109 defproxy.defsrv.check_port = 0;
1110 defproxy.defsrv.maxqueue = 0;
1111 defproxy.defsrv.minconn = 0;
1112 defproxy.defsrv.maxconn = 0;
1113 defproxy.defsrv.slowstart = 0;
1114 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1115 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1116 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117}
1118
Willy Tarreauade5ec42010-01-28 19:33:49 +01001119
1120static int create_cond_regex_rule(const char *file, int line,
1121 struct proxy *px, int dir, int action, int flags,
1122 const char *cmd, const char *reg, const char *repl,
1123 const char **cond_start)
1124{
1125 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001126 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 const char *err;
1128 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001129 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130
1131 if (px == &defproxy) {
1132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (*reg == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1144 err_code |= ERR_WARN;
1145
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 if (cond_start &&
1147 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001148 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1149 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1150 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto err;
1153 }
1154 }
1155 else if (cond_start && **cond_start) {
1156 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1157 file, line, cmd, *cond_start);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001163 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001164 else
1165 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001166
Willy Tarreauade5ec42010-01-28 19:33:49 +01001167 preg = calloc(1, sizeof(regex_t));
1168 if (!preg) {
1169 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1170 err_code = ERR_ALERT | ERR_FATAL;
1171 goto err;
1172 }
1173
1174 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1175 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1176 err_code = ERR_ALERT | ERR_FATAL;
1177 goto err;
1178 }
1179
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001180 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001181 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001182 if (repl && err) {
1183 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1184 file, line, cmd, *err);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto err;
1187 }
1188
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001189 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 err_code |= ERR_WARN;
1191
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 return err_code;
1194 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001195 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001196 free(preg);
1197 return err_code;
1198}
1199
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001202 * Returns the error code, 0 if OK, or any combination of :
1203 * - ERR_ABORT: must abort ASAP
1204 * - ERR_FATAL: we can continue parsing but not start the service
1205 * - ERR_WARN: a warning has been emitted
1206 * - ERR_ALERT: an alert has been emitted
1207 * Only the two first ones can stop processing, the two others are just
1208 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001210int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1211{
1212 static struct peers *curpeers = NULL;
1213 struct peer *newpeer = NULL;
1214 const char *err;
1215 int err_code = 0;
1216
1217 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1218
1219 err = invalid_char(args[1]);
1220 if (err) {
1221 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1222 file, linenum, *err, args[0], args[1]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 }
1225
1226 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1227 /*
1228 * If there are two proxies with the same name only following
1229 * combinations are allowed:
1230 */
1231 if (strcmp(curpeers->id, args[1]) == 0) {
1232 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1233 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1234 err_code |= ERR_WARN;
1235 }
1236 }
1237
1238 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1240 err_code |= ERR_ALERT | ERR_ABORT;
1241 goto out;
1242 }
1243
1244 curpeers->next = peers;
1245 peers = curpeers;
1246 curpeers->conf.file = file;
1247 curpeers->conf.line = linenum;
1248 curpeers->last_change = now.tv_sec;
1249 curpeers->id = strdup(args[1]);
1250 }
1251 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1252 char *rport, *raddr;
1253 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001254 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (!*args[2]) {
1257 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1258 file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 err = invalid_char(args[1]);
1264 if (err) {
1265 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1266 file, linenum, *err, args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 /* the peers are linked backwards first */
1278 curpeers->count++;
1279 newpeer->next = curpeers->remote;
1280 curpeers->remote = newpeer;
1281 newpeer->peers = curpeers;
1282 newpeer->conf.file = file;
1283 newpeer->conf.line = linenum;
1284
1285 newpeer->last_change = now.tv_sec;
1286 newpeer->id = strdup(args[1]);
1287
1288 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001289 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 if (rport) {
1291 *rport++ = 0;
1292 realport = atol(rport);
1293 }
1294 if (!realport) {
1295 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
Willy Tarreaufab5a432011-03-04 15:31:53 +01001300 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 free(raddr);
1302 if (!sk) {
1303 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001308 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001309 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
1312 if (!sk) {
1313 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1314 file, linenum, newpeer->addr.ss_family, args[2]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001319 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320
1321 if (strcmp(newpeer->id, localpeer) == 0) {
1322 /* Current is local peer, it define a frontend */
1323 newpeer->local = 1;
1324
1325 if (!curpeers->peers_fe) {
1326 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 err_code |= ERR_ALERT | ERR_ABORT;
1329 goto out;
1330 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001331
Willy Tarreau237250c2011-07-29 01:49:03 +02001332 init_new_proxy(curpeers->peers_fe);
1333 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001334
1335 curpeers->peers_fe->last_change = now.tv_sec;
1336 curpeers->peers_fe->id = strdup(args[1]);
1337 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001338 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1340 curpeers->peers_fe->timeout.connect = 5000;
1341 curpeers->peers_fe->accept = peer_accept;
1342 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001343 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001344 err_code |= ERR_FATAL;
1345 goto out;
1346 }
1347 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1348 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1349 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1350 curpeers->peers_fe->listen->accept = session_accept;
1351 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1352 curpeers->peers_fe->listen->handler = process_session;
1353 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001354 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1355 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001356 }
1357 }
1358 } /* neither "peer" nor "peers" */
1359 else if (*args[0] != 0) {
1360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364
1365out:
1366 return err_code;
1367}
1368
1369
Willy Tarreau3842f002009-06-14 11:39:52 +02001370int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371{
1372 static struct proxy *curproxy = NULL;
1373 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001374 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001375 int rc;
1376 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001377 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001378 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001379 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001380 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381
Willy Tarreau977b8e42006-12-29 14:19:17 +01001382 if (!strcmp(args[0], "listen"))
1383 rc = PR_CAP_LISTEN;
1384 else if (!strcmp(args[0], "frontend"))
1385 rc = PR_CAP_FE | PR_CAP_RS;
1386 else if (!strcmp(args[0], "backend"))
1387 rc = PR_CAP_BE | PR_CAP_RS;
1388 else if (!strcmp(args[0], "ruleset"))
1389 rc = PR_CAP_RS;
1390 else
1391 rc = PR_CAP_NONE;
1392
1393 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 if (!*args[1]) {
1395 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1396 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_ALERT | ERR_ABORT;
1399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001401
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001402 err = invalid_char(args[1]);
1403 if (err) {
1404 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1405 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001407 }
1408
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001409 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1410 /*
1411 * If there are two proxies with the same name only following
1412 * combinations are allowed:
1413 *
1414 * listen backend frontend ruleset
1415 * listen - - - -
1416 * backend - - OK -
1417 * frontend - OK - -
1418 * ruleset - - - -
1419 */
1420
1421 if (!strcmp(curproxy->id, args[1]) &&
1422 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1423 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001424 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1425 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1426 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001427 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001428 }
1429 }
1430
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1432 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001433 err_code |= ERR_ALERT | ERR_ABORT;
1434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001436
Willy Tarreau97cb7802010-01-03 20:23:58 +01001437 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 curproxy->next = proxy;
1439 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001440 curproxy->conf.file = file;
1441 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001442 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
1446 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001448 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001449 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001450 err_code |= ERR_FATAL;
1451 goto out;
1452 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001453 new = curproxy->listen;
1454 while (new != last) {
1455 new->conf.file = file;
1456 new->conf.line = linenum;
1457 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001458 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 }
1461
1462 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001463 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001464 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001465
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001468 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001469 curproxy->no_options = defproxy.no_options;
1470 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001471 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001472 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001473 curproxy->except_net = defproxy.except_net;
1474 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001475 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001476 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001478 if (defproxy.fwdfor_hdr_len) {
1479 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1480 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1481 }
1482
Willy Tarreaub86db342009-11-30 11:50:16 +01001483 if (defproxy.orgto_hdr_len) {
1484 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1485 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1486 }
1487
Mark Lamourinec2247f02012-01-04 13:02:01 -05001488 if (defproxy.server_id_hdr_len) {
1489 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1490 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1491 }
1492
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 if (curproxy->cap & PR_CAP_FE) {
1494 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001495 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001496 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497
1498 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001499 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1500 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501
1502 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 if (curproxy->cap & PR_CAP_BE) {
1506 curproxy->fullconn = defproxy.fullconn;
1507 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001509 if (defproxy.check_req) {
1510 curproxy->check_req = calloc(1, defproxy.check_len);
1511 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1512 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001515 if (defproxy.expect_str) {
1516 curproxy->expect_str = strdup(defproxy.expect_str);
1517 if (defproxy.expect_regex) {
1518 /* note: this regex is known to be valid */
1519 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1520 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1521 }
1522 }
1523
Willy Tarreau67402132012-05-31 20:40:20 +02001524 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 if (defproxy.cookie_name)
1526 curproxy->cookie_name = strdup(defproxy.cookie_name);
1527 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001528 if (defproxy.cookie_domain)
1529 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001530
Willy Tarreau31936852010-10-06 16:59:56 +02001531 if (defproxy.cookie_maxidle)
1532 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1533
1534 if (defproxy.cookie_maxlife)
1535 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1536
Emeric Brun647caf12009-06-30 17:57:00 +02001537 if (defproxy.rdp_cookie_name)
1538 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1539 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1540
Willy Tarreau01732802007-11-01 22:48:15 +01001541 if (defproxy.url_param_name)
1542 curproxy->url_param_name = strdup(defproxy.url_param_name);
1543 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001544
Benoitaffb4812009-03-25 13:02:10 +01001545 if (defproxy.hh_name)
1546 curproxy->hh_name = strdup(defproxy.hh_name);
1547 curproxy->hh_len = defproxy.hh_len;
1548 curproxy->hh_match_domain = defproxy.hh_match_domain;
1549
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001550 if (defproxy.iface_name)
1551 curproxy->iface_name = strdup(defproxy.iface_name);
1552 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001555 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 if (defproxy.capture_name)
1557 curproxy->capture_name = strdup(defproxy.capture_name);
1558 curproxy->capture_namelen = defproxy.capture_namelen;
1559 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561
Willy Tarreau977b8e42006-12-29 14:19:17 +01001562 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001563 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001564 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001565 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001566 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 curproxy->uri_auth = defproxy.uri_auth;
1568 curproxy->mon_net = defproxy.mon_net;
1569 curproxy->mon_mask = defproxy.mon_mask;
1570 if (defproxy.monitor_uri)
1571 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1572 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001573 if (defproxy.defbe.name)
1574 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001575
1576 /* get either a pointer to the logformat string or a copy of it */
1577 curproxy->logformat_string = defproxy.logformat_string;
1578 if (curproxy->logformat_string &&
1579 curproxy->logformat_string != default_http_log_format &&
1580 curproxy->logformat_string != default_tcp_log_format &&
1581 curproxy->logformat_string != clf_http_log_format)
1582 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001583 }
1584
1585 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001586 curproxy->timeout.connect = defproxy.timeout.connect;
1587 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001588 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001589 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001590 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001591 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001592 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001593 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001594 curproxy->source_addr = defproxy.source_addr;
1595 }
1596
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001598
1599 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001600 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001601 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001602 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001603 LIST_INIT(&node->list);
1604 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1605 }
1606
Willy Tarreau196729e2012-05-31 19:30:26 +02001607 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1608 if (curproxy->uniqueid_format_string)
1609 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001610
1611 /* copy default header unique id */
1612 if (defproxy.header_unique_id)
1613 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1614
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001616 curproxy->conf.used_listener_id = EB_ROOT;
1617 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001618
Willy Tarreau93893792009-07-23 13:19:11 +02001619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
1621 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1622 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001623 /* FIXME-20070101: we should do this too at the end of the
1624 * config parsing to free all default values.
1625 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001626 free(defproxy.check_req);
1627 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001628 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001629 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001630 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001631 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001632 free(defproxy.capture_name);
1633 free(defproxy.monitor_uri);
1634 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001635 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001636 free(defproxy.fwdfor_hdr_name);
1637 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001638 free(defproxy.orgto_hdr_name);
1639 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001640 free(defproxy.server_id_hdr_name);
1641 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001642 free(defproxy.expect_str);
1643 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001644
Willy Tarreau39b06652012-06-01 10:58:06 +02001645 if (defproxy.logformat_string != default_http_log_format &&
1646 defproxy.logformat_string != default_tcp_log_format &&
1647 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001648 free(defproxy.logformat_string);
1649
1650 free(defproxy.uniqueid_format_string);
1651
Willy Tarreaua534fea2008-08-03 12:19:50 +02001652 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001653 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001654
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 /* we cannot free uri_auth because it might already be used */
1656 init_default_instance();
1657 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001658 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001659 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 }
1661 else if (curproxy == NULL) {
1662 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666
Willy Tarreau977b8e42006-12-29 14:19:17 +01001667
1668 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001671 int cur_arg;
1672
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 if (curproxy == &defproxy) {
1674 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001675 err_code |= ERR_ALERT | ERR_FATAL;
1676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001678 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001682 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001687
1688 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001689
1690 /* NOTE: the following line might create several listeners if there
1691 * are comma-separated IPs or port ranges. So all further processing
1692 * will have to be applied to all listeners created after last_listen.
1693 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001694 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001698
Willy Tarreau90a570f2009-10-04 20:54:54 +02001699 new_listen = curproxy->listen;
1700 while (new_listen != last_listen) {
1701 new_listen->conf.file = file;
1702 new_listen->conf.line = linenum;
1703 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001704 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001705 }
1706
Emeric Bruned760922010-10-22 17:59:25 +02001707 /* Set default global rights and owner for unix bind */
1708 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1709 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1710 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001711 cur_arg = 2;
1712 while (*(args[cur_arg])) {
1713 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1714#ifdef SO_BINDTODEVICE
1715 struct listener *l;
1716
Emeric Bruned760922010-10-22 17:59:25 +02001717 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1719 file, linenum, args[0], args[cur_arg]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001724 if (!*args[cur_arg + 1]) {
1725 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001729 }
1730
1731 for (l = curproxy->listen; l != last_listen; l = l->next)
1732 l->interface = strdup(args[cur_arg + 1]);
1733
1734 global.last_checks |= LSTCHK_NETADM;
1735
1736 cur_arg += 2;
1737 continue;
1738#else
1739 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1740 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001743#endif
1744 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001745 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1746#ifdef TCP_MAXSEG
1747 struct listener *l;
1748 int mss;
1749
Emeric Bruned760922010-10-22 17:59:25 +02001750 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1752 file, linenum, args[0], args[cur_arg]);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756
Willy Tarreaube1b9182009-06-14 18:48:19 +02001757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1759 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001762 }
1763
Willy Tarreau48a7e722010-12-24 15:26:39 +01001764 mss = atoi(args[cur_arg + 1]);
1765 if (!mss || abs(mss) > 65535) {
1766 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001770 }
1771
1772 for (l = curproxy->listen; l != last_listen; l = l->next)
1773 l->maxseg = mss;
1774
1775 cur_arg += 2;
1776 continue;
1777#else
1778 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1779 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001782#endif
1783 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001784
1785 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1786#ifdef TCP_DEFER_ACCEPT
1787 struct listener *l;
1788
1789 for (l = curproxy->listen; l != last_listen; l = l->next)
1790 l->options |= LI_O_DEF_ACCEPT;
1791
1792 cur_arg ++;
1793 continue;
1794#else
1795 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1796 file, linenum, args[0], args[cur_arg]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799#endif
1800 }
1801
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001802 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001803#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001804 struct listener *l;
1805
Emeric Bruned760922010-10-22 17:59:25 +02001806 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1807 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1808 file, linenum, args[0], args[cur_arg]);
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001813 for (l = curproxy->listen; l != last_listen; l = l->next)
1814 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001815
1816 cur_arg ++;
1817 continue;
1818#else
1819 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1820 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001823#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001824 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001825
Willy Tarreau32368ce2012-09-06 11:10:55 +02001826 if (!strcmp(args[cur_arg], "maxconn")) {
1827 struct listener *l;
1828 int val;
1829
1830 if (!*args[cur_arg + 1]) {
1831 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1832 file, linenum, args[0]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836
1837 val = atol(args[cur_arg + 1]);
1838 if (val <= 0) {
1839 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1840 file, linenum, args[0], val);
1841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
1843 }
1844
1845 for (l = curproxy->listen; l != last_listen; l = l->next)
1846 l->maxconn = val;
1847
1848 cur_arg += 2;
1849 continue;
1850 }
1851
1852 if (!strcmp(args[cur_arg], "backlog")) {
1853 struct listener *l;
1854 int val;
1855
1856 if (!*args[cur_arg + 1]) {
1857 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1858 file, linenum, args[0]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862
1863 val = atol(args[cur_arg + 1]);
1864 if (val <= 0) {
1865 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1866 file, linenum, args[0], val);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870
1871 for (l = curproxy->listen; l != last_listen; l = l->next)
1872 l->backlog = val;
1873
1874 cur_arg += 2;
1875 continue;
1876 }
1877
Emeric Brun6e159292012-05-18 16:32:13 +02001878 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1879#ifdef USE_OPENSSL
1880 struct listener *l;
1881
1882 if (!*args[cur_arg + 1]) {
1883 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1884 file, linenum, args[0]);
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 }
1888
1889 for (l = curproxy->listen; l != last_listen; l = l->next)
1890 l->ssl_cert = strdup(args[cur_arg + 1]);
1891
1892 cur_arg += 2;
1893 continue;
1894#else
1895 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1896 file, linenum, args[0], args[cur_arg]);
1897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
1899#endif
1900 }
1901
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001902 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1903#ifdef USE_OPENSSL
1904 struct listener *l;
1905
1906 if (!*args[cur_arg + 1]) {
1907 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1908 file, linenum, args[0]);
1909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
1911 }
1912
1913 for (l = curproxy->listen; l != last_listen; l = l->next)
1914 l->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
1915
1916 cur_arg += 2;
1917 continue;
1918#else
1919 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1920 file, linenum, args[0], args[cur_arg]);
1921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
1923#endif
1924 }
1925
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001926 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1927#ifdef USE_OPENSSL
1928 struct listener *l;
1929
1930 for (l = curproxy->listen; l != last_listen; l = l->next)
1931 l->ssl_ctx.nosslv3 = 1;
1932
1933 cur_arg += 1;
1934 continue;
1935#else
1936 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1937 file, linenum, args[0], args[cur_arg]);
1938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
1940#endif
1941 }
1942
1943 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1944#ifdef USE_OPENSSL
1945 struct listener *l;
1946
1947 for (l = curproxy->listen; l != last_listen; l = l->next)
1948 l->ssl_ctx.notlsv1 = 1;
1949
1950 cur_arg += 1;
1951 continue;
1952#else
1953 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1954 file, linenum, args[0], args[cur_arg]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957#endif
1958 }
1959
David BERARDe566ecb2012-09-04 15:15:13 +02001960 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1961#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
1962 struct listener *l;
1963
1964 for (l = curproxy->listen; l != last_listen; l = l->next)
1965 l->ssl_ctx.prefer_server_ciphers = 1;
1966
1967 cur_arg += 1;
1968 continue;
1969#else
1970 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1971 file, linenum, args[0], args[cur_arg]);
1972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
1974#endif
1975 }
1976
Willy Tarreau8a956912010-10-15 14:27:08 +02001977 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1978 struct listener *l;
1979
1980 for (l = curproxy->listen; l != last_listen; l = l->next)
1981 l->options |= LI_O_ACC_PROXY;
1982
1983 cur_arg ++;
1984 continue;
1985 }
1986
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001987 if (!strcmp(args[cur_arg], "name")) {
1988 struct listener *l;
1989
1990 for (l = curproxy->listen; l != last_listen; l = l->next)
1991 l->name = strdup(args[cur_arg + 1]);
1992
1993 cur_arg += 2;
1994 continue;
1995 }
1996
1997 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001998 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001999 struct listener *l;
2000
2001 if (curproxy->listen->next != last_listen) {
2002 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
2003 file, linenum, args[cur_arg]);
2004 err_code |= ERR_ALERT | ERR_FATAL;
2005 goto out;
2006 }
2007
2008 if (!*args[cur_arg + 1]) {
2009 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2010 file, linenum, args[cur_arg]);
2011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
2013 }
2014
2015 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002016 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002017
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002018 if (curproxy->listen->luid <= 0) {
2019 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002020 file, linenum);
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002025 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
2026 if (node) {
2027 l = container_of(node, struct listener, conf.id);
2028 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
2029 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
2030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
2032 }
2033 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
2034
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002035 cur_arg += 2;
2036 continue;
2037 }
2038
Emeric Bruned760922010-10-22 17:59:25 +02002039 if (!strcmp(args[cur_arg], "mode")) {
2040
2041 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2042 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2043 file, linenum, args[0], args[cur_arg]);
2044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
2046 }
2047
2048 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
2049
2050 cur_arg += 2;
2051 continue;
2052 }
2053
2054 if (!strcmp(args[cur_arg], "uid")) {
2055
2056 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2057 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2058 file, linenum, args[0], args[cur_arg]);
2059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
2062
2063 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
2064 cur_arg += 2;
2065 continue;
2066 }
2067
2068 if (!strcmp(args[cur_arg], "gid")) {
2069
2070 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2071 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2072 file, linenum, args[0], args[cur_arg]);
2073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
2075 }
2076
2077 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2078 cur_arg += 2;
2079 continue;
2080 }
2081
2082 if (!strcmp(args[cur_arg], "user")) {
2083 struct passwd *user;
2084
2085 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2086 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2087 file, linenum, args[0], args[cur_arg]);
2088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
2090 }
2091 user = getpwnam(args[cur_arg + 1]);
2092 if (!user) {
2093 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2094 file, linenum, args[0], args[cur_arg + 1 ]);
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
2097 }
2098
2099 curproxy->listen->perm.ux.uid = user->pw_uid;
2100 cur_arg += 2;
2101 continue;
2102 }
2103
2104 if (!strcmp(args[cur_arg], "group")) {
2105 struct group *group;
2106
2107 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2108 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2109 file, linenum, args[0], args[cur_arg]);
2110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
2112 }
2113 group = getgrnam(args[cur_arg + 1]);
2114 if (!group) {
2115 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2116 file, linenum, args[0], args[cur_arg + 1 ]);
2117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
2119 }
2120
2121 curproxy->listen->perm.ux.gid = group->gr_gid;
2122 cur_arg += 2;
2123 continue;
2124 }
2125
Willy Tarreaub48f9582011-09-05 01:17:06 +02002126 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002127 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002130 }
Willy Tarreau93893792009-07-23 13:19:11 +02002131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 }
2133 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2134 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2135 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2136 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002140 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002141 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002142
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 /* flush useless bits */
2144 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002147 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002148 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002150
Willy Tarreau1c47f852006-07-09 08:22:27 +02002151 if (!*args[1]) {
2152 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002156 }
2157
Willy Tarreaua534fea2008-08-03 12:19:50 +02002158 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002159 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002160 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002161 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002162 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2163
Willy Tarreau93893792009-07-23 13:19:11 +02002164 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2167 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2168 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2169 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2170 else {
2171 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 }
2175 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002176 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002177 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002178
2179 if (curproxy == &defproxy) {
2180 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002184 }
2185
2186 if (!*args[1]) {
2187 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002191 }
2192
2193 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002194 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002195
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002196 if (curproxy->uuid <= 0) {
2197 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002198 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002201 }
2202
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002203 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2204 if (node) {
2205 struct proxy *target = container_of(node, struct proxy, conf.id);
2206 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2207 file, linenum, proxy_type_str(curproxy), curproxy->id,
2208 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
2211 }
2212 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002213 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002214 else if (!strcmp(args[0], "description")) {
2215 int i, len=0;
2216 char *d;
2217
Cyril Bonté99ed3272010-01-24 23:29:44 +01002218 if (curproxy == &defproxy) {
2219 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2220 file, linenum, args[0]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002225 if (!*args[1]) {
2226 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2227 file, linenum, args[0]);
2228 return -1;
2229 }
2230
2231 for(i=1; *args[i]; i++)
2232 len += strlen(args[i])+1;
2233
2234 d = (char *)calloc(1, len);
2235 curproxy->desc = d;
2236
2237 d += sprintf(d, "%s", args[1]);
2238 for(i=2; *args[i]; i++)
2239 d += sprintf(d, " %s", args[i]);
2240
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2243 curproxy->state = PR_STSTOPPED;
2244 }
2245 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2246 curproxy->state = PR_STNEW;
2247 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2249 int cur_arg = 1;
2250 unsigned int set = 0;
2251
2252 while (*args[cur_arg]) {
2253 int u;
2254 if (strcmp(args[cur_arg], "all") == 0) {
2255 set = 0;
2256 break;
2257 }
2258 else if (strcmp(args[cur_arg], "odd") == 0) {
2259 set |= 0x55555555;
2260 }
2261 else if (strcmp(args[cur_arg], "even") == 0) {
2262 set |= 0xAAAAAAAA;
2263 }
2264 else {
2265 u = str2uic(args[cur_arg]);
2266 if (u < 1 || u > 32) {
2267 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002271 }
2272 if (u > global.nbproc) {
2273 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2274 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002276 }
2277 set |= 1 << (u - 1);
2278 }
2279 cur_arg++;
2280 }
2281 curproxy->bind_proc = set;
2282 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002283 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002284 if (curproxy == &defproxy) {
2285 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002288 }
2289
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002290 err = invalid_char(args[1]);
2291 if (err) {
2292 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2293 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002295 }
2296
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002297 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2298 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2299 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002302 }
2303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2305 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306
Willy Tarreau977b8e42006-12-29 14:19:17 +01002307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002309
Willy Tarreaubaaee002006-06-26 02:48:02 +02002310 if (*(args[1]) == 0) {
2311 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002316
Willy Tarreau67402132012-05-31 20:40:20 +02002317 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002318 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002319 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002320 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 curproxy->cookie_name = strdup(args[1]);
2322 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002323
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 cur_arg = 2;
2325 while (*(args[cur_arg])) {
2326 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002327 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
2329 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002330 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
2332 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002333 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 }
2335 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002336 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 }
2338 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002339 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002341 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002342 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002345 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002347 else if (!strcmp(args[cur_arg], "httponly")) {
2348 curproxy->ck_opts |= PR_CK_HTTPONLY;
2349 }
2350 else if (!strcmp(args[cur_arg], "secure")) {
2351 curproxy->ck_opts |= PR_CK_SECURE;
2352 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002353 else if (!strcmp(args[cur_arg], "domain")) {
2354 if (!*args[cur_arg + 1]) {
2355 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2356 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002359 }
2360
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002361 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002362 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002363 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2364 " dots nor does not start with a dot."
2365 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002366 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002367 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002368 }
2369
2370 err = invalid_domainchar(args[cur_arg + 1]);
2371 if (err) {
2372 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2373 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002376 }
2377
Willy Tarreau68a897b2009-12-03 23:28:34 +01002378 if (!curproxy->cookie_domain) {
2379 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2380 } else {
2381 /* one domain was already specified, add another one by
2382 * building the string which will be returned along with
2383 * the cookie.
2384 */
2385 char *new_ptr;
2386 int new_len = strlen(curproxy->cookie_domain) +
2387 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2388 new_ptr = malloc(new_len);
2389 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2390 free(curproxy->cookie_domain);
2391 curproxy->cookie_domain = new_ptr;
2392 }
Willy Tarreau31936852010-10-06 16:59:56 +02002393 cur_arg++;
2394 }
2395 else if (!strcmp(args[cur_arg], "maxidle")) {
2396 unsigned int maxidle;
2397 const char *res;
2398
2399 if (!*args[cur_arg + 1]) {
2400 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2401 file, linenum, args[cur_arg]);
2402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
2404 }
2405
2406 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2407 if (res) {
2408 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2409 file, linenum, *res, args[cur_arg]);
2410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
2412 }
2413 curproxy->cookie_maxidle = maxidle;
2414 cur_arg++;
2415 }
2416 else if (!strcmp(args[cur_arg], "maxlife")) {
2417 unsigned int maxlife;
2418 const char *res;
2419
2420 if (!*args[cur_arg + 1]) {
2421 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2422 file, linenum, args[cur_arg]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426
2427 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2428 if (res) {
2429 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2430 file, linenum, *res, args[cur_arg]);
2431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
2433 }
2434 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002435 cur_arg++;
2436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002438 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 cur_arg++;
2444 }
Willy Tarreau67402132012-05-31 20:40:20 +02002445 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2447 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
2450
Willy Tarreau67402132012-05-31 20:40:20 +02002451 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002456
Willy Tarreau67402132012-05-31 20:40:20 +02002457 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002458 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2459 file, linenum);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002463 else if (!strcmp(args[0], "persist")) { /* persist */
2464 if (*(args[1]) == 0) {
2465 Alert("parsing [%s:%d] : missing persist method.\n",
2466 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002469 }
2470
2471 if (!strncmp(args[1], "rdp-cookie", 10)) {
2472 curproxy->options2 |= PR_O2_RDPC_PRST;
2473
Emeric Brunb982a3d2010-01-04 15:45:53 +01002474 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002475 const char *beg, *end;
2476
2477 beg = args[1] + 11;
2478 end = strchr(beg, ')');
2479
2480 if (!end || end == beg) {
2481 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2482 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002485 }
2486
2487 free(curproxy->rdp_cookie_name);
2488 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2489 curproxy->rdp_cookie_len = end-beg;
2490 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002491 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002492 free(curproxy->rdp_cookie_name);
2493 curproxy->rdp_cookie_name = strdup("msts");
2494 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2495 }
2496 else { /* syntax */
2497 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2498 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002501 }
2502 }
2503 else {
2504 Alert("parsing [%s:%d] : unknown persist method.\n",
2505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002508 }
2509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002511 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002513 if (curproxy == &defproxy) {
2514 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
2517 }
2518
Willy Tarreau977b8e42006-12-29 14:19:17 +01002519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002521
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002523 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
2528 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002529 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 curproxy->appsession_name = strdup(args[1]);
2531 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2532 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002533 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2534 if (err) {
2535 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2536 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002539 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002540 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002541
Willy Tarreau51041c72007-09-09 21:56:53 +02002542 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2543 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_ABORT;
2545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002547
2548 cur_arg = 6;
2549 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002550 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2551 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002552 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002553 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002554 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002555 } else if (!strcmp(args[cur_arg], "prefix")) {
2556 curproxy->options2 |= PR_O2_AS_PFX;
2557 } else if (!strcmp(args[cur_arg], "mode")) {
2558 if (!*args[cur_arg + 1]) {
2559 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2560 file, linenum, args[0], args[cur_arg]);
2561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
2563 }
2564
2565 cur_arg++;
2566 if (!strcmp(args[cur_arg], "query-string")) {
2567 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2568 curproxy->options2 |= PR_O2_AS_M_QS;
2569 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2570 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2571 curproxy->options2 |= PR_O2_AS_M_PP;
2572 } else {
2573 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002578 cur_arg++;
2579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 } /* Url App Session */
2581 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002582 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002586 if (curproxy == &defproxy) {
2587 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
2590 }
2591
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 if (*(args[4]) == 0) {
2593 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002598 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 curproxy->capture_name = strdup(args[2]);
2600 curproxy->capture_namelen = strlen(curproxy->capture_name);
2601 curproxy->capture_len = atol(args[4]);
2602 if (curproxy->capture_len >= CAPTURE_LEN) {
2603 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2604 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 curproxy->capture_len = CAPTURE_LEN - 1;
2607 }
2608 curproxy->to_log |= LW_COOKIE;
2609 }
2610 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2611 struct cap_hdr *hdr;
2612
2613 if (curproxy == &defproxy) {
2614 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 }
2618
2619 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2620 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2621 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
2625
2626 hdr = calloc(sizeof(struct cap_hdr), 1);
2627 hdr->next = curproxy->req_cap;
2628 hdr->name = strdup(args[3]);
2629 hdr->namelen = strlen(args[3]);
2630 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002631 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 hdr->index = curproxy->nb_req_cap++;
2633 curproxy->req_cap = hdr;
2634 curproxy->to_log |= LW_REQHDR;
2635 }
2636 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2637 struct cap_hdr *hdr;
2638
2639 if (curproxy == &defproxy) {
2640 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644
2645 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2646 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2647 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651 hdr = calloc(sizeof(struct cap_hdr), 1);
2652 hdr->next = curproxy->rsp_cap;
2653 hdr->name = strdup(args[3]);
2654 hdr->namelen = strlen(args[3]);
2655 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002656 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 hdr->index = curproxy->nb_rsp_cap++;
2658 curproxy->rsp_cap = hdr;
2659 curproxy->to_log |= LW_RSPHDR;
2660 }
2661 else {
2662 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
2667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002669 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (*(args[1]) == 0) {
2673 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 }
2678 curproxy->conn_retries = atol(args[1]);
2679 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002680 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002681 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002682
2683 if (curproxy == &defproxy) {
2684 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688
Willy Tarreauff011f22011-01-06 17:51:27 +01002689 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002690 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2691 file, linenum, args[0]);
2692 err_code |= ERR_WARN;
2693 }
2694
Willy Tarreauff011f22011-01-06 17:51:27 +01002695 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002696
Willy Tarreauff011f22011-01-06 17:51:27 +01002697 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002698 err_code |= ERR_ALERT | ERR_ABORT;
2699 goto out;
2700 }
2701
Willy Tarreauff011f22011-01-06 17:51:27 +01002702 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2703 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002704 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002705 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2706 /* set the header name and length into the proxy structure */
2707 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2708 err_code |= ERR_WARN;
2709
2710 if (!*args[1]) {
2711 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2712 file, linenum, args[0]);
2713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
2717 /* set the desired header name */
2718 free(curproxy->server_id_hdr_name);
2719 curproxy->server_id_hdr_name = strdup(args[1]);
2720 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2721 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002722 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002727 }
2728
Willy Tarreauef6494c2010-01-28 17:12:36 +01002729 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002730 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2731 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002734 }
2735
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002736 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2737 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2738 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002741 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002742
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002743 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002744 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002745 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002746 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002747 struct redirect_rule *rule;
2748 int cur_arg;
2749 int type = REDIRECT_TYPE_NONE;
2750 int code = 302;
2751 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002752 char *cookie = NULL;
2753 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002754 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002755
Cyril Bonté99ed3272010-01-24 23:29:44 +01002756 if (curproxy == &defproxy) {
2757 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002762 cur_arg = 1;
2763 while (*(args[cur_arg])) {
2764 if (!strcmp(args[cur_arg], "location")) {
2765 if (!*args[cur_arg + 1]) {
2766 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2767 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002770 }
2771
2772 type = REDIRECT_TYPE_LOCATION;
2773 cur_arg++;
2774 destination = args[cur_arg];
2775 }
2776 else if (!strcmp(args[cur_arg], "prefix")) {
2777 if (!*args[cur_arg + 1]) {
2778 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2779 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002782 }
2783
2784 type = REDIRECT_TYPE_PREFIX;
2785 cur_arg++;
2786 destination = args[cur_arg];
2787 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002788 else if (!strcmp(args[cur_arg], "set-cookie")) {
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2791 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002794 }
2795
2796 cur_arg++;
2797 cookie = args[cur_arg];
2798 cookie_set = 1;
2799 }
2800 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2801 if (!*args[cur_arg + 1]) {
2802 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2803 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002806 }
2807
2808 cur_arg++;
2809 cookie = args[cur_arg];
2810 cookie_set = 0;
2811 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002812 else if (!strcmp(args[cur_arg],"code")) {
2813 if (!*args[cur_arg + 1]) {
2814 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2815 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002818 }
2819 cur_arg++;
2820 code = atol(args[cur_arg]);
2821 if (code < 301 || code > 303) {
2822 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2823 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002826 }
2827 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002828 else if (!strcmp(args[cur_arg],"drop-query")) {
2829 flags |= REDIRECT_FLAG_DROP_QS;
2830 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002831 else if (!strcmp(args[cur_arg],"append-slash")) {
2832 flags |= REDIRECT_FLAG_APPEND_SLASH;
2833 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002834 else if (strcmp(args[cur_arg], "if") == 0 ||
2835 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002836 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002837 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002838 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2839 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002843 break;
2844 }
2845 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002846 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002847 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002850 }
2851 cur_arg++;
2852 }
2853
2854 if (type == REDIRECT_TYPE_NONE) {
2855 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002859 }
2860
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002861 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2862 rule->cond = cond;
2863 rule->rdr_str = strdup(destination);
2864 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002865 if (cookie) {
2866 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002867 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002868 */
2869 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002870 if (cookie_set) {
2871 rule->cookie_str = malloc(rule->cookie_len + 10);
2872 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2873 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2874 rule->cookie_len += 9;
2875 } else {
2876 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002877 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002878 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2879 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002880 }
2881 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002882 rule->type = type;
2883 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002884 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002885 LIST_INIT(&rule->list);
2886 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002887 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2888 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002889 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002890 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002891 struct switching_rule *rule;
2892
Willy Tarreaub099aca2008-10-12 17:26:37 +02002893 if (curproxy == &defproxy) {
2894 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002897 }
2898
Willy Tarreau55ea7572007-06-17 19:56:27 +02002899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002901
2902 if (*(args[1]) == 0) {
2903 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002906 }
2907
Willy Tarreauef6494c2010-01-28 17:12:36 +01002908 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002909 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2910 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002913 }
2914
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2916 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2917 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002920 }
2921
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002922 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002923
Willy Tarreau55ea7572007-06-17 19:56:27 +02002924 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2925 rule->cond = cond;
2926 rule->be.name = strdup(args[1]);
2927 LIST_INIT(&rule->list);
2928 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2929 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002930 else if (strcmp(args[0], "use-server") == 0) {
2931 struct server_rule *rule;
2932
2933 if (curproxy == &defproxy) {
2934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2940 err_code |= ERR_WARN;
2941
2942 if (*(args[1]) == 0) {
2943 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
2947
2948 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2949 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2950 file, linenum, args[0]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002955 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2956 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2957 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
2961
2962 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2963
2964 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2965 rule->cond = cond;
2966 rule->srv.name = strdup(args[1]);
2967 LIST_INIT(&rule->list);
2968 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2969 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2970 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002971 else if ((!strcmp(args[0], "force-persist")) ||
2972 (!strcmp(args[0], "ignore-persist"))) {
2973 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002974
2975 if (curproxy == &defproxy) {
2976 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
2980
2981 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2982 err_code |= ERR_WARN;
2983
Willy Tarreauef6494c2010-01-28 17:12:36 +01002984 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002985 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2986 file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2992 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2993 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002998 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002999
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003000 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003001 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003002 if (!strcmp(args[0], "force-persist")) {
3003 rule->type = PERSIST_TYPE_FORCE;
3004 } else {
3005 rule->type = PERSIST_TYPE_IGNORE;
3006 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003007 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003008 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003009 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 else if (!strcmp(args[0], "stick-table")) {
3011 int myidx = 1;
3012
Emeric Brun32da3c42010-09-23 18:39:19 +02003013 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 curproxy->table.type = (unsigned int)-1;
3015 while (*args[myidx]) {
3016 const char *err;
3017
3018 if (strcmp(args[myidx], "size") == 0) {
3019 myidx++;
3020 if (!*(args[myidx])) {
3021 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3022 file, linenum, args[myidx-1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3027 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3028 file, linenum, *err, args[myidx-1]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003032 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003034 else if (strcmp(args[myidx], "peers") == 0) {
3035 myidx++;
3036 if (!*(args[myidx])) {
3037 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3038 file, linenum, args[myidx-1]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
3041 }
3042 curproxy->table.peers.name = strdup(args[myidx++]);
3043 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 else if (strcmp(args[myidx], "expire") == 0) {
3045 myidx++;
3046 if (!*(args[myidx])) {
3047 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3048 file, linenum, args[myidx-1]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3053 if (err) {
3054 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3055 file, linenum, *err, args[myidx-1]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
3058 }
3059 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003060 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003061 }
3062 else if (strcmp(args[myidx], "nopurge") == 0) {
3063 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003064 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 }
3066 else if (strcmp(args[myidx], "type") == 0) {
3067 myidx++;
3068 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3069 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3070 file, linenum, args[myidx]);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003074 /* myidx already points to next arg */
3075 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003076 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003077 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003078 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003079
3080 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003081 nw = args[myidx];
3082 while (*nw) {
3083 /* the "store" keyword supports a comma-separated list */
3084 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003085 sa = NULL; /* store arg */
3086 while (*nw && *nw != ',') {
3087 if (*nw == '(') {
3088 *nw = 0;
3089 sa = ++nw;
3090 while (*nw != ')') {
3091 if (!*nw) {
3092 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3093 file, linenum, args[0], cw);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097 nw++;
3098 }
3099 *nw = '\0';
3100 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003101 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003102 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003103 if (*nw)
3104 *nw++ = '\0';
3105 type = stktable_get_data_type(cw);
3106 if (type < 0) {
3107 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3108 file, linenum, args[0], cw);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
3111 }
Willy Tarreauac782882010-06-20 10:41:54 +02003112
3113 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3114 switch (err) {
3115 case PE_NONE: break;
3116 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003117 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3118 file, linenum, args[0], cw);
3119 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003120 break;
3121
3122 case PE_ARG_MISSING:
3123 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3124 file, linenum, args[0], cw);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127
3128 case PE_ARG_NOT_USED:
3129 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3130 file, linenum, args[0], cw);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133
3134 default:
3135 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3136 file, linenum, args[0], cw);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003139 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003140 }
3141 myidx++;
3142 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003143 else {
3144 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3145 file, linenum, args[myidx]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003148 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 }
3150
3151 if (!curproxy->table.size) {
3152 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3153 file, linenum);
3154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
3158 if (curproxy->table.type == (unsigned int)-1) {
3159 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3160 file, linenum);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164 }
3165 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003167 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003168 int myidx = 0;
3169 const char *name = NULL;
3170 int flags;
3171
3172 if (curproxy == &defproxy) {
3173 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
3178 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3179 err_code |= ERR_WARN;
3180 goto out;
3181 }
3182
3183 myidx++;
3184 if ((strcmp(args[myidx], "store") == 0) ||
3185 (strcmp(args[myidx], "store-request") == 0)) {
3186 myidx++;
3187 flags = STK_IS_STORE;
3188 }
3189 else if (strcmp(args[myidx], "store-response") == 0) {
3190 myidx++;
3191 flags = STK_IS_STORE | STK_ON_RSP;
3192 }
3193 else if (strcmp(args[myidx], "match") == 0) {
3194 myidx++;
3195 flags = STK_IS_MATCH;
3196 }
3197 else if (strcmp(args[myidx], "on") == 0) {
3198 myidx++;
3199 flags = STK_IS_MATCH | STK_IS_STORE;
3200 }
3201 else {
3202 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (*(args[myidx]) == 0) {
3208 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
3211 }
3212
David du Colombier7af46052012-05-16 14:16:48 +02003213 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003214 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003215 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
3220 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003221 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3223 file, linenum, args[0], expr->fetch->kw);
3224 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003225 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003226 goto out;
3227 }
3228 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003229 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003230 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3231 file, linenum, args[0], expr->fetch->kw);
3232 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003233 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003234 goto out;
3235 }
3236 }
3237
3238 if (strcmp(args[myidx], "table") == 0) {
3239 myidx++;
3240 name = args[myidx++];
3241 }
3242
Willy Tarreauef6494c2010-01-28 17:12:36 +01003243 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003244 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3245 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3246 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003248 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 goto out;
3250 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003251 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003252 else if (*(args[myidx])) {
3253 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3254 file, linenum, args[0], args[myidx]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003256 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003257 goto out;
3258 }
Emeric Brun97679e72010-09-23 17:56:44 +02003259 if (flags & STK_ON_RSP)
3260 err_code |= warnif_cond_requires_req(cond, file, linenum);
3261 else
3262 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003263
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3265 rule->cond = cond;
3266 rule->expr = expr;
3267 rule->flags = flags;
3268 rule->table.name = name ? strdup(name) : NULL;
3269 LIST_INIT(&rule->list);
3270 if (flags & STK_ON_RSP)
3271 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3272 else
3273 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003276 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003278
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3280 curproxy->uri_auth = NULL; /* we must detach from the default config */
3281
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003282 if (!*args[1]) {
3283 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003284 } else if (!strcmp(args[1], "admin")) {
3285 struct stats_admin_rule *rule;
3286
3287 if (curproxy == &defproxy) {
3288 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292
3293 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3294 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3295 err_code |= ERR_ALERT | ERR_ABORT;
3296 goto out;
3297 }
3298
3299 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3300 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3301 file, linenum, args[0], args[1]);
3302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
3304 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003305 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3306 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3307 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
3311
3312 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3313
3314 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3315 rule->cond = cond;
3316 LIST_INIT(&rule->list);
3317 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 } else if (!strcmp(args[1], "uri")) {
3319 if (*(args[2]) == 0) {
3320 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_ABORT;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328 } else if (!strcmp(args[1], "realm")) {
3329 if (*(args[2]) == 0) {
3330 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_ABORT;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003338 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003339 unsigned interval;
3340
3341 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3342 if (err) {
3343 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3344 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003347 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_ABORT;
3350 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003351 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003352 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003353 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003354
3355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3362 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3363 err_code |= ERR_ALERT | ERR_ABORT;
3364 goto out;
3365 }
3366
Willy Tarreauff011f22011-01-06 17:51:27 +01003367 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3368 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003369 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3370 file, linenum, args[0]);
3371 err_code |= ERR_WARN;
3372 }
3373
Willy Tarreauff011f22011-01-06 17:51:27 +01003374 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003375
Willy Tarreauff011f22011-01-06 17:51:27 +01003376 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003377 err_code |= ERR_ALERT | ERR_ABORT;
3378 goto out;
3379 }
3380
Willy Tarreauff011f22011-01-06 17:51:27 +01003381 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3382 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003383
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 } else if (!strcmp(args[1], "auth")) {
3385 if (*(args[2]) == 0) {
3386 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_ABORT;
3392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 } else if (!strcmp(args[1], "scope")) {
3395 if (*(args[2]) == 0) {
3396 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_ABORT;
3402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
3404 } else if (!strcmp(args[1], "enable")) {
3405 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3406 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_ALERT | ERR_ABORT;
3408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003410 } else if (!strcmp(args[1], "hide-version")) {
3411 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_ALERT | ERR_ABORT;
3414 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003415 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003416 } else if (!strcmp(args[1], "show-legends")) {
3417 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3418 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3419 err_code |= ERR_ALERT | ERR_ABORT;
3420 goto out;
3421 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003422 } else if (!strcmp(args[1], "show-node")) {
3423
3424 if (*args[2]) {
3425 int i;
3426 char c;
3427
3428 for (i=0; args[2][i]; i++) {
3429 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003430 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3431 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003432 break;
3433 }
3434
3435 if (!i || args[2][i]) {
3436 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3437 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3438 file, linenum, args[0], args[1]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 }
3443
3444 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3445 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3446 err_code |= ERR_ALERT | ERR_ABORT;
3447 goto out;
3448 }
3449 } else if (!strcmp(args[1], "show-desc")) {
3450 char *desc = NULL;
3451
3452 if (*args[2]) {
3453 int i, len=0;
3454 char *d;
3455
3456 for(i=2; *args[i]; i++)
3457 len += strlen(args[i])+1;
3458
3459 desc = d = (char *)calloc(1, len);
3460
3461 d += sprintf(d, "%s", args[2]);
3462 for(i=3; *args[i]; i++)
3463 d += sprintf(d, " %s", args[i]);
3464 }
3465
3466 if (!*args[2] && !global.desc)
3467 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3468 file, linenum, args[1]);
3469 else {
3470 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3471 free(desc);
3472 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3473 err_code |= ERR_ALERT | ERR_ABORT;
3474 goto out;
3475 }
3476 free(desc);
3477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003479stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003480 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003481 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 }
3485 }
3486 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003487 int optnum;
3488
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003489 if (*(args[1]) == '\0') {
3490 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003495
3496 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3497 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003498 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3499 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3500 file, linenum, cfg_opts[optnum].name);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
Willy Tarreau93893792009-07-23 13:19:11 +02003504 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3505 err_code |= ERR_WARN;
3506 goto out;
3507 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003508
Willy Tarreau3842f002009-06-14 11:39:52 +02003509 curproxy->no_options &= ~cfg_opts[optnum].val;
3510 curproxy->options &= ~cfg_opts[optnum].val;
3511
3512 switch (kwm) {
3513 case KWM_STD:
3514 curproxy->options |= cfg_opts[optnum].val;
3515 break;
3516 case KWM_NO:
3517 curproxy->no_options |= cfg_opts[optnum].val;
3518 break;
3519 case KWM_DEF: /* already cleared */
3520 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003521 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003522
Willy Tarreau93893792009-07-23 13:19:11 +02003523 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003524 }
3525 }
3526
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003527 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3528 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003529 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3530 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3531 file, linenum, cfg_opts2[optnum].name);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
Willy Tarreau93893792009-07-23 13:19:11 +02003535 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3536 err_code |= ERR_WARN;
3537 goto out;
3538 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003539
Willy Tarreau3842f002009-06-14 11:39:52 +02003540 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3541 curproxy->options2 &= ~cfg_opts2[optnum].val;
3542
3543 switch (kwm) {
3544 case KWM_STD:
3545 curproxy->options2 |= cfg_opts2[optnum].val;
3546 break;
3547 case KWM_NO:
3548 curproxy->no_options2 |= cfg_opts2[optnum].val;
3549 break;
3550 case KWM_DEF: /* already cleared */
3551 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003552 }
Willy Tarreau93893792009-07-23 13:19:11 +02003553 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003554 }
3555 }
3556
Willy Tarreau3842f002009-06-14 11:39:52 +02003557 if (kwm != KWM_STD) {
3558 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003559 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003562 }
3563
Emeric Brun3a058f32009-06-30 18:26:00 +02003564 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003565 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003567 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003568 if (*(args[2]) != '\0') {
3569 if (!strcmp(args[2], "clf")) {
3570 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003571 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003572 } else {
3573 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003576 }
3577 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003578 if (curproxy->logformat_string != default_http_log_format &&
3579 curproxy->logformat_string != default_tcp_log_format &&
3580 curproxy->logformat_string != clf_http_log_format)
3581 free(curproxy->logformat_string);
3582 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003583 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003584 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003585 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003586 if (curproxy->logformat_string != default_http_log_format &&
3587 curproxy->logformat_string != default_tcp_log_format &&
3588 curproxy->logformat_string != clf_http_log_format)
3589 free(curproxy->logformat_string);
3590 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003592 else if (!strcmp(args[1], "tcpka")) {
3593 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003594 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003596
3597 if (curproxy->cap & PR_CAP_FE)
3598 curproxy->options |= PR_O_TCP_CLI_KA;
3599 if (curproxy->cap & PR_CAP_BE)
3600 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003601 }
3602 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_WARN;
3605
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003607 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003608 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003609 curproxy->options2 &= ~PR_O2_CHK_ANY;
3610 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 if (!*args[2]) { /* no argument */
3612 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3613 curproxy->check_len = strlen(DEF_CHECK_REQ);
3614 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003615 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 curproxy->check_req = (char *)malloc(reqlen);
3617 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003618 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003620 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 if (*args[4])
3622 reqlen += strlen(args[4]);
3623 else
3624 reqlen += strlen("HTTP/1.0");
3625
3626 curproxy->check_req = (char *)malloc(reqlen);
3627 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003628 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003629 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003630 }
3631 else if (!strcmp(args[1], "ssl-hello-chk")) {
3632 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003633 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003635
Willy Tarreaua534fea2008-08-03 12:19:50 +02003636 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003637 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003638 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003639 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 }
Willy Tarreau23677902007-05-08 23:50:35 +02003641 else if (!strcmp(args[1], "smtpchk")) {
3642 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003643 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003644 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003645 curproxy->options2 &= ~PR_O2_CHK_ANY;
3646 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003647
3648 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3649 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3650 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3651 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3652 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3653 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3654 curproxy->check_req = (char *)malloc(reqlen);
3655 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3656 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3657 } else {
3658 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3659 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3660 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3661 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3662 }
3663 }
3664 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003665 else if (!strcmp(args[1], "pgsql-check")) {
3666 /* use PostgreSQL request to check servers' health */
3667 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3668 err_code |= ERR_WARN;
3669
3670 free(curproxy->check_req);
3671 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003672 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003673 curproxy->options2 |= PR_O2_PGSQL_CHK;
3674
3675 if (*(args[2])) {
3676 int cur_arg = 2;
3677
3678 while (*(args[cur_arg])) {
3679 if (strcmp(args[cur_arg], "user") == 0) {
3680 char * packet;
3681 uint32_t packet_len;
3682 uint32_t pv;
3683
3684 /* suboption header - needs additional argument for it */
3685 if (*(args[cur_arg+1]) == 0) {
3686 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3687 file, linenum, args[0], args[1], args[cur_arg]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
3692 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3693 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3694 pv = htonl(0x30000); /* protocol version 3.0 */
3695
3696 packet = (char*) calloc(1, packet_len);
3697
3698 memcpy(packet + 4, &pv, 4);
3699
3700 /* copy "user" */
3701 memcpy(packet + 8, "user", 4);
3702
3703 /* copy username */
3704 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3705
3706 free(curproxy->check_req);
3707 curproxy->check_req = packet;
3708 curproxy->check_len = packet_len;
3709
3710 packet_len = htonl(packet_len);
3711 memcpy(packet, &packet_len, 4);
3712 cur_arg += 2;
3713 } else {
3714 /* unknown suboption - catchall */
3715 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3716 file, linenum, args[0], args[1]);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 } /* end while loop */
3721 }
3722 }
3723
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003724 else if (!strcmp(args[1], "redis-check")) {
3725 /* use REDIS PING request to check servers' health */
3726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3727 err_code |= ERR_WARN;
3728
3729 free(curproxy->check_req);
3730 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003731 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003732 curproxy->options2 |= PR_O2_REDIS_CHK;
3733
3734 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3735 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3736 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3737 }
3738
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003739 else if (!strcmp(args[1], "mysql-check")) {
3740 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3742 err_code |= ERR_WARN;
3743
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003744 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003745 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003746 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003747 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003748
3749 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3750 * const char mysql40_client_auth_pkt[] = {
3751 * "\x0e\x00\x00" // packet length
3752 * "\x01" // packet number
3753 * "\x00\x00" // client capabilities
3754 * "\x00\x00\x01" // max packet
3755 * "haproxy\x00" // username (null terminated string)
3756 * "\x00" // filler (always 0x00)
3757 * "\x01\x00\x00" // packet length
3758 * "\x00" // packet number
3759 * "\x01" // COM_QUIT command
3760 * };
3761 */
3762
3763 if (*(args[2])) {
3764 int cur_arg = 2;
3765
3766 while (*(args[cur_arg])) {
3767 if (strcmp(args[cur_arg], "user") == 0) {
3768 char *mysqluser;
3769 int packetlen, reqlen, userlen;
3770
3771 /* suboption header - needs additional argument for it */
3772 if (*(args[cur_arg+1]) == 0) {
3773 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3774 file, linenum, args[0], args[1], args[cur_arg]);
3775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
3777 }
3778 mysqluser = args[cur_arg + 1];
3779 userlen = strlen(mysqluser);
3780 packetlen = userlen + 7;
3781 reqlen = packetlen + 9;
3782
3783 free(curproxy->check_req);
3784 curproxy->check_req = (char *)calloc(1, reqlen);
3785 curproxy->check_len = reqlen;
3786
3787 snprintf(curproxy->check_req, 4, "%c%c%c",
3788 ((unsigned char) packetlen & 0xff),
3789 ((unsigned char) (packetlen >> 8) & 0xff),
3790 ((unsigned char) (packetlen >> 16) & 0xff));
3791
3792 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003793 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003794 curproxy->check_req[8] = 1;
3795 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3796 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3797 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3798 cur_arg += 2;
3799 } else {
3800 /* unknown suboption - catchall */
3801 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3802 file, linenum, args[0], args[1]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806 } /* end while loop */
3807 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003808 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003809 else if (!strcmp(args[1], "ldap-check")) {
3810 /* use LDAP request to check servers' health */
3811 free(curproxy->check_req);
3812 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003813 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003814 curproxy->options2 |= PR_O2_LDAP_CHK;
3815
3816 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3817 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3818 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3819 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003820 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003821 int cur_arg;
3822
3823 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3824 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003825 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003826
Willy Tarreau87cf5142011-08-19 22:57:24 +02003827 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003828
3829 free(curproxy->fwdfor_hdr_name);
3830 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3831 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3832
3833 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3834 cur_arg = 2;
3835 while (*(args[cur_arg])) {
3836 if (!strcmp(args[cur_arg], "except")) {
3837 /* suboption except - needs additional argument for it */
3838 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3839 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3840 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003843 }
3844 /* flush useless bits */
3845 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003846 cur_arg += 2;
3847 } else if (!strcmp(args[cur_arg], "header")) {
3848 /* suboption header - needs additional argument for it */
3849 if (*(args[cur_arg+1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3851 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003854 }
3855 free(curproxy->fwdfor_hdr_name);
3856 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3857 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3858 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003859 } else if (!strcmp(args[cur_arg], "if-none")) {
3860 curproxy->options &= ~PR_O_FF_ALWAYS;
3861 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003862 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003863 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003864 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003865 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003868 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003869 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003870 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003871 else if (!strcmp(args[1], "originalto")) {
3872 int cur_arg;
3873
3874 /* insert x-original-to field, but not for the IP address listed as an except.
3875 * set default options (ie: bitfield, header name, etc)
3876 */
3877
3878 curproxy->options |= PR_O_ORGTO;
3879
3880 free(curproxy->orgto_hdr_name);
3881 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3882 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3883
Willy Tarreau87cf5142011-08-19 22:57:24 +02003884 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003885 cur_arg = 2;
3886 while (*(args[cur_arg])) {
3887 if (!strcmp(args[cur_arg], "except")) {
3888 /* suboption except - needs additional argument for it */
3889 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3890 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3891 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003894 }
3895 /* flush useless bits */
3896 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3897 cur_arg += 2;
3898 } else if (!strcmp(args[cur_arg], "header")) {
3899 /* suboption header - needs additional argument for it */
3900 if (*(args[cur_arg+1]) == 0) {
3901 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3902 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003905 }
3906 free(curproxy->orgto_hdr_name);
3907 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3908 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3909 cur_arg += 2;
3910 } else {
3911 /* unknown suboption - catchall */
3912 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3913 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003916 }
3917 } /* end while loop */
3918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 else {
3920 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 }
Willy Tarreau93893792009-07-23 13:19:11 +02003924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003926 else if (!strcmp(args[0], "default_backend")) {
3927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003929
3930 if (*(args[1]) == 0) {
3931 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003934 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003935 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003936 curproxy->defbe.name = strdup(args[1]);
3937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003941
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003942 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 /* enable reconnections to dispatch */
3946 curproxy->options |= PR_O_REDISP;
3947 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003948 else if (!strcmp(args[0], "http-check")) {
3949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003951
3952 if (strcmp(args[1], "disable-on-404") == 0) {
3953 /* enable a graceful server shutdown on an HTTP 404 response */
3954 curproxy->options |= PR_O_DISABLE404;
3955 }
Willy Tarreauef781042010-01-27 11:53:01 +01003956 else if (strcmp(args[1], "send-state") == 0) {
3957 /* enable emission of the apparent state of a server in HTTP checks */
3958 curproxy->options2 |= PR_O2_CHK_SNDST;
3959 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003960 else if (strcmp(args[1], "expect") == 0) {
3961 const char *ptr_arg;
3962 int cur_arg;
3963
3964 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3965 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
3970 cur_arg = 2;
3971 /* consider exclamation marks, sole or at the beginning of a word */
3972 while (*(ptr_arg = args[cur_arg])) {
3973 while (*ptr_arg == '!') {
3974 curproxy->options2 ^= PR_O2_EXP_INV;
3975 ptr_arg++;
3976 }
3977 if (*ptr_arg)
3978 break;
3979 cur_arg++;
3980 }
3981 /* now ptr_arg points to the beginning of a word past any possible
3982 * exclamation mark, and cur_arg is the argument which holds this word.
3983 */
3984 if (strcmp(ptr_arg, "status") == 0) {
3985 if (!*(args[cur_arg + 1])) {
3986 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3987 file, linenum, args[0], args[1], ptr_arg);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
3991 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003992 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003993 curproxy->expect_str = strdup(args[cur_arg + 1]);
3994 }
3995 else if (strcmp(ptr_arg, "string") == 0) {
3996 if (!*(args[cur_arg + 1])) {
3997 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3998 file, linenum, args[0], args[1], ptr_arg);
3999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
4001 }
4002 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004003 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004004 curproxy->expect_str = strdup(args[cur_arg + 1]);
4005 }
4006 else if (strcmp(ptr_arg, "rstatus") == 0) {
4007 if (!*(args[cur_arg + 1])) {
4008 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4009 file, linenum, args[0], args[1], ptr_arg);
4010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
4012 }
4013 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004014 free(curproxy->expect_str);
4015 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4016 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004017 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4018 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4019 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4020 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
4024 }
4025 else if (strcmp(ptr_arg, "rstring") == 0) {
4026 if (!*(args[cur_arg + 1])) {
4027 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4028 file, linenum, args[0], args[1], ptr_arg);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
4032 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004033 free(curproxy->expect_str);
4034 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4035 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004036 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4037 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4038 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4039 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043 }
4044 else {
4045 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4046 file, linenum, args[0], args[1], ptr_arg);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
4050 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004051 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004052 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004055 }
4056 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004057 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004058 if (curproxy == &defproxy) {
4059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004062 }
4063
Willy Tarreaub80c2302007-11-30 20:51:32 +01004064 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004066
4067 if (strcmp(args[1], "fail") == 0) {
4068 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004069 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004070 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4071 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004074 }
4075
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004076 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4077 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4078 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004081 }
4082 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4083 }
4084 else {
4085 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004088 }
4089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090#ifdef TPROXY
4091 else if (!strcmp(args[0], "transparent")) {
4092 /* enable transparent proxy connections */
4093 curproxy->options |= PR_O_TRANSP;
4094 }
4095#endif
4096 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004097 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004099
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 if (*(args[1]) == 0) {
4101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 }
4105 curproxy->maxconn = atol(args[1]);
4106 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004107 else if (!strcmp(args[0], "backlog")) { /* backlog */
4108 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004110
4111 if (*(args[1]) == 0) {
4112 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004115 }
4116 curproxy->backlog = atol(args[1]);
4117 }
Willy Tarreau86034312006-12-29 00:10:33 +01004118 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004119 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004121
Willy Tarreau86034312006-12-29 00:10:33 +01004122 if (*(args[1]) == 0) {
4123 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004126 }
4127 curproxy->fullconn = atol(args[1]);
4128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4130 if (*(args[1]) == 0) {
4131 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004135 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4136 if (err) {
4137 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4138 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004141 }
4142 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 }
4144 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004145 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 if (curproxy == &defproxy) {
4147 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004151 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004153
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 if (strchr(args[1], ':') == NULL) {
4155 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004159 sk = str2sa(args[1]);
4160 if (!sk) {
4161 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004166 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 }
4168 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004169 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004171
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004172 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4173 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004178 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4180 err_code |= ERR_WARN;
4181
4182 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4183 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4184 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4185 }
4186 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4187 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4188 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4189 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004190 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4191 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4192 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4193 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004194 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004195 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198 }
4199 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004200 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202 char *rport, *raddr;
4203 short realport = 0;
4204 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004206 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004207 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004211 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213
4214 if (!*args[2]) {
4215 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4216 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004220
4221 err = invalid_char(args[1]);
4222 if (err) {
4223 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4224 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004227 }
4228
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004229 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004230 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004231
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004232 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4233 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4234 err_code |= ERR_ALERT | ERR_ABORT;
4235 goto out;
4236 }
4237
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004238 /* the servers are linked backwards first */
4239 newsrv->next = curproxy->srv;
4240 curproxy->srv = newsrv;
4241 newsrv->proxy = curproxy;
4242 newsrv->conf.file = file;
4243 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244
Simon Hormanaf514952011-06-21 14:34:57 +09004245 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004246 LIST_INIT(&newsrv->pendconns);
4247 do_check = 0;
4248 newsrv->state = SRV_RUNNING; /* early server setup */
4249 newsrv->last_change = now.tv_sec;
4250 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004252 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004253 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004254 * - IP: => port=+0, relative
4255 * - IP:N => port=N, absolute
4256 * - IP:+N => port=+N, relative
4257 * - IP:-N => port=-N, relative
4258 */
4259 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004260 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004261 if (rport) {
4262 *rport++ = 0;
4263 realport = atol(rport);
4264 if (!isdigit((unsigned char)*rport))
4265 newsrv->state |= SRV_MAPPORTS;
4266 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004268
Willy Tarreaufab5a432011-03-04 15:31:53 +01004269 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004270 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004271 if (!sk) {
4272 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004277 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004278 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004279
4280 if (!sk) {
4281 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4282 file, linenum, newsrv->addr.ss_family, args[2]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004286 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004287
4288 newsrv->check_port = curproxy->defsrv.check_port;
4289 newsrv->inter = curproxy->defsrv.inter;
4290 newsrv->fastinter = curproxy->defsrv.fastinter;
4291 newsrv->downinter = curproxy->defsrv.downinter;
4292 newsrv->rise = curproxy->defsrv.rise;
4293 newsrv->fall = curproxy->defsrv.fall;
4294 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4295 newsrv->minconn = curproxy->defsrv.minconn;
4296 newsrv->maxconn = curproxy->defsrv.maxconn;
4297 newsrv->slowstart = curproxy->defsrv.slowstart;
4298 newsrv->onerror = curproxy->defsrv.onerror;
4299 newsrv->consecutive_errors_limit
4300 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004301#ifdef OPENSSL
4302 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4303#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004304 newsrv->uweight = newsrv->iweight
4305 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004307 newsrv->curfd = -1; /* no health-check in progress */
4308 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004310 cur_arg = 3;
4311 } else {
4312 newsrv = &curproxy->defsrv;
4313 cur_arg = 1;
4314 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004315
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004317 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004318 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004319
4320 if (!*args[cur_arg + 1]) {
4321 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4322 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004325 }
4326
4327 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004328 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004329
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004330 if (newsrv->puid <= 0) {
4331 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004332 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004335 }
4336
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004337 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4338 if (node) {
4339 struct server *target = container_of(node, struct server, conf.id);
4340 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4341 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004346 cur_arg += 2;
4347 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004348 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 newsrv->cookie = strdup(args[cur_arg + 1]);
4350 newsrv->cklen = strlen(args[cur_arg + 1]);
4351 cur_arg += 2;
4352 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004353 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004354 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4355 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4356 cur_arg += 2;
4357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004359 if (!*args[cur_arg + 1]) {
4360 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4361 file, linenum, args[cur_arg]);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365
Willy Tarreaubaaee002006-06-26 02:48:02 +02004366 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004367 if (newsrv->rise <= 0) {
4368 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4369 file, linenum, args[cur_arg]);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373
Willy Tarreau96839092010-03-29 10:02:24 +02004374 if (newsrv->health)
4375 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 cur_arg += 2;
4377 }
4378 else if (!strcmp(args[cur_arg], "fall")) {
4379 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004380
4381 if (!*args[cur_arg + 1]) {
4382 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4383 file, linenum, args[cur_arg]);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387
4388 if (newsrv->fall <= 0) {
4389 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4390 file, linenum, args[cur_arg]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 cur_arg += 2;
4396 }
4397 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004398 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4399 if (err) {
4400 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4401 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004404 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004405 if (val <= 0) {
4406 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4407 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004410 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004411 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 cur_arg += 2;
4413 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004414 else if (!strcmp(args[cur_arg], "fastinter")) {
4415 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4416 if (err) {
4417 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4418 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004421 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004422 if (val <= 0) {
4423 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4424 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004427 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004428 newsrv->fastinter = val;
4429 cur_arg += 2;
4430 }
4431 else if (!strcmp(args[cur_arg], "downinter")) {
4432 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4433 if (err) {
4434 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4435 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004438 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004439 if (val <= 0) {
4440 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4441 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004444 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004445 newsrv->downinter = val;
4446 cur_arg += 2;
4447 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004448 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004449 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004450 if (!sk) {
4451 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
4454 }
4455 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004456 cur_arg += 2;
4457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458 else if (!strcmp(args[cur_arg], "port")) {
4459 newsrv->check_port = atol(args[cur_arg + 1]);
4460 cur_arg += 2;
4461 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004462 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 newsrv->state |= SRV_BACKUP;
4464 cur_arg ++;
4465 }
Simon Hormanfa461682011-06-25 09:39:49 +09004466 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4467 newsrv->state |= SRV_NON_STICK;
4468 cur_arg ++;
4469 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004470 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4471 newsrv->state |= SRV_SEND_PROXY;
4472 cur_arg ++;
4473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 else if (!strcmp(args[cur_arg], "weight")) {
4475 int w;
4476 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004477 if (w < 0 || w > 256) {
4478 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004483 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 cur_arg += 2;
4485 }
4486 else if (!strcmp(args[cur_arg], "minconn")) {
4487 newsrv->minconn = atol(args[cur_arg + 1]);
4488 cur_arg += 2;
4489 }
4490 else if (!strcmp(args[cur_arg], "maxconn")) {
4491 newsrv->maxconn = atol(args[cur_arg + 1]);
4492 cur_arg += 2;
4493 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004494 else if (!strcmp(args[cur_arg], "maxqueue")) {
4495 newsrv->maxqueue = atol(args[cur_arg + 1]);
4496 cur_arg += 2;
4497 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004498 else if (!strcmp(args[cur_arg], "slowstart")) {
4499 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004500 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004501 if (err) {
4502 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4503 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004506 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004507 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004508 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4509 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004512 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004513 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004514 cur_arg += 2;
4515 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004516 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004517
4518 if (!*args[cur_arg + 1]) {
4519 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4520 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004523 }
4524
4525 newsrv->trackit = strdup(args[cur_arg + 1]);
4526
4527 cur_arg += 2;
4528 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004529 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 global.maxsock++;
4531 do_check = 1;
4532 cur_arg += 1;
4533 }
Willy Tarreau96839092010-03-29 10:02:24 +02004534 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4535 newsrv->state |= SRV_MAINTAIN;
4536 newsrv->state &= ~SRV_RUNNING;
4537 newsrv->health = 0;
4538 cur_arg += 1;
4539 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004540 else if (!strcmp(args[cur_arg], "ssl")) {
4541#ifdef USE_OPENSSL
4542 newsrv->use_ssl = 1;
4543 cur_arg += 1;
4544#else /* USE_OPENSSL */
4545 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4546 file, linenum, args[cur_arg]);
4547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549#endif /* USE_OPENSSL */
4550 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004551 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4552#ifdef USE_OPENSSL
4553 if (!*args[cur_arg + 1]) {
4554 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4555 file, linenum, args[0], args[cur_arg]);
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559
4560 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4561
4562 cur_arg += 2;
4563 continue;
4564#else
4565 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4566 file, linenum, args[0], args[cur_arg]);
4567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569#endif
4570 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004571 else if (!strcmp(args[cur_arg], "nosslv3")) {
4572#ifdef USE_OPENSSL
4573 newsrv->ssl_ctx.nosslv3 = 1;
4574 cur_arg += 1;
4575#else /* USE_OPENSSL */
4576 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4577 file, linenum, args[cur_arg]);
4578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
4580#endif /* USE_OPENSSL */
4581 }
4582 else if (!strcmp(args[cur_arg], "notlsv1")) {
4583#ifdef USE_OPENSSL
4584 newsrv->ssl_ctx.notlsv1 = 1;
4585 cur_arg += 1;
4586#else /* USE_OPENSSL */
4587 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4588 file, linenum, args[cur_arg]);
4589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
4591#endif /* USE_OPENSSL */
4592 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004593 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004594 if (!strcmp(args[cur_arg + 1], "none"))
4595 newsrv->observe = HANA_OBS_NONE;
4596 else if (!strcmp(args[cur_arg + 1], "layer4"))
4597 newsrv->observe = HANA_OBS_LAYER4;
4598 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4599 if (curproxy->mode != PR_MODE_HTTP) {
4600 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4601 file, linenum, args[cur_arg + 1]);
4602 err_code |= ERR_ALERT;
4603 }
4604 newsrv->observe = HANA_OBS_LAYER7;
4605 }
4606 else {
4607 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004608 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004609 file, linenum, args[cur_arg], args[cur_arg + 1]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613
4614 cur_arg += 2;
4615 }
4616 else if (!strcmp(args[cur_arg], "on-error")) {
4617 if (!strcmp(args[cur_arg + 1], "fastinter"))
4618 newsrv->onerror = HANA_ONERR_FASTINTER;
4619 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4620 newsrv->onerror = HANA_ONERR_FAILCHK;
4621 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4622 newsrv->onerror = HANA_ONERR_SUDDTH;
4623 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4624 newsrv->onerror = HANA_ONERR_MARKDWN;
4625 else {
4626 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004627 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004628 file, linenum, args[cur_arg], args[cur_arg + 1]);
4629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631 }
4632
4633 cur_arg += 2;
4634 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004635 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4636 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4637 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4638 else {
4639 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4640 file, linenum, args[cur_arg], args[cur_arg + 1]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
4644
4645 cur_arg += 2;
4646 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004647 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4648 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4649 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4650 else {
4651 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4652 file, linenum, args[cur_arg], args[cur_arg + 1]);
4653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655 }
4656
4657 cur_arg += 2;
4658 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004659 else if (!strcmp(args[cur_arg], "error-limit")) {
4660 if (!*args[cur_arg + 1]) {
4661 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4662 file, linenum, args[cur_arg]);
4663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665 }
4666
4667 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4668
4669 if (newsrv->consecutive_errors_limit <= 0) {
4670 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4671 file, linenum, args[cur_arg]);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004675 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004676 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004677 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004678 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004679 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004680
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004682#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004683 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004684 file, linenum, "source", "usesrc");
4685#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004686 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004688#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 }
4692 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004693 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4694 if (!sk) {
4695 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
4698 }
4699 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004700
4701 if (port_low != port_high) {
4702 int i;
4703 if (port_low <= 0 || port_low > 65535 ||
4704 port_high <= 0 || port_high > 65535 ||
4705 port_low > port_high) {
4706 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4707 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004710 }
4711 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4712 for (i = 0; i < newsrv->sport_range->size; i++)
4713 newsrv->sport_range->ports[i] = port_low + i;
4714 }
4715
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004717 while (*(args[cur_arg])) {
4718 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004719#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4720#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004721 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4722 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4723 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004726 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004728 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004729 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004730 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004733 }
4734 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004735 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004736 newsrv->state |= SRV_TPROXY_CLI;
4737 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004738 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004739 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004740 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4741 char *name, *end;
4742
4743 name = args[cur_arg+1] + 7;
4744 while (isspace(*name))
4745 name++;
4746
4747 end = name;
4748 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4749 end++;
4750
4751 newsrv->state &= ~SRV_TPROXY_MASK;
4752 newsrv->state |= SRV_TPROXY_DYN;
4753 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4754 newsrv->bind_hdr_len = end - name;
4755 memcpy(newsrv->bind_hdr_name, name, end - name);
4756 newsrv->bind_hdr_name[end-name] = '\0';
4757 newsrv->bind_hdr_occ = -1;
4758
4759 /* now look for an occurrence number */
4760 while (isspace(*end))
4761 end++;
4762 if (*end == ',') {
4763 end++;
4764 name = end;
4765 if (*end == '-')
4766 end++;
4767 while (isdigit(*end))
4768 end++;
4769 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4770 }
4771
4772 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4773 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4774 " occurrences values smaller than %d.\n",
4775 file, linenum, MAX_HDR_HISTORY);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004779 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004780 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004781 if (!sk) {
4782 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
4786 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004787 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004788 }
4789 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004790#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004791 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004792#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004793 cur_arg += 2;
4794 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004795#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004796 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004797 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004800#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4801 } /* "usesrc" */
4802
4803 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4804#ifdef SO_BINDTODEVICE
4805 if (!*args[cur_arg + 1]) {
4806 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4807 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004810 }
4811 if (newsrv->iface_name)
4812 free(newsrv->iface_name);
4813
4814 newsrv->iface_name = strdup(args[cur_arg + 1]);
4815 newsrv->iface_len = strlen(newsrv->iface_name);
4816 global.last_checks |= LSTCHK_NETADM;
4817#else
4818 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4819 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004822#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004823 cur_arg += 2;
4824 continue;
4825 }
4826 /* this keyword in not an option of "source" */
4827 break;
4828 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004830 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004831 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4832 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004837 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004838 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004839 file, linenum, newsrv->id);
4840 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004841 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004842 file, linenum);
4843
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
4847 }
4848
4849 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004850 if (newsrv->trackit) {
4851 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4852 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004855 }
4856
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004857 /* try to get the port from check_addr if check_port not set */
4858 if (!newsrv->check_port)
4859 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004860
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4862 newsrv->check_port = realport; /* by default */
4863 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004864 /* not yet valid, because no port was set on
4865 * the server either. We'll check if we have
4866 * a known port on the first listener.
4867 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004868 struct listener *l = curproxy->listen;
4869 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4870 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004871 }
4872 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4874 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004878
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004879 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004880 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004881 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4882 err_code |= ERR_ALERT | ERR_ABORT;
4883 goto out;
4884 }
4885
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004886 /* Allocate buffer for partial check results... */
4887 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4888 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4889 err_code |= ERR_ALERT | ERR_ABORT;
4890 goto out;
4891 }
4892
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004893 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 newsrv->state |= SRV_CHECKED;
4895 }
4896
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004897 if (!defsrv) {
4898 if (newsrv->state & SRV_BACKUP)
4899 curproxy->srv_bck++;
4900 else
4901 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004902
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004903 newsrv->prev_state = newsrv->state;
4904 }
William Lallemanda73203e2012-03-12 12:48:57 +01004905 }
4906
4907 else if (strcmp(args[0], "unique-id-format") == 0) {
4908 if (!*(args[1])) {
4909 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
4912 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004913 free(curproxy->uniqueid_format_string);
4914 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004915 }
William Lallemanda73203e2012-03-12 12:48:57 +01004916
4917 else if (strcmp(args[0], "unique-id-header") == 0) {
4918 if (!*(args[1])) {
4919 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923 free(curproxy->header_unique_id);
4924 curproxy->header_unique_id = strdup(args[1]);
4925 }
4926
William Lallemand723b73a2012-02-08 16:37:49 +01004927 else if (strcmp(args[0], "log-format") == 0) {
4928 if (!*(args[1])) {
4929 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004933
4934 if (curproxy->logformat_string != default_http_log_format &&
4935 curproxy->logformat_string != default_tcp_log_format &&
4936 curproxy->logformat_string != clf_http_log_format)
4937 free(curproxy->logformat_string);
4938 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
William Lallemand723b73a2012-02-08 16:37:49 +01004940
William Lallemand0f99e342011-10-12 17:50:54 +02004941 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4942 /* delete previous herited or defined syslog servers */
4943 struct logsrv *back;
4944
4945 if (*(args[1]) != 0) {
4946 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
4949 }
4950
William Lallemand723b73a2012-02-08 16:37:49 +01004951 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4952 LIST_DEL(&tmplogsrv->list);
4953 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004954 }
4955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004957 struct logsrv *logsrv;
4958
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004960 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004961 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004962 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004963 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004964 LIST_INIT(&node->list);
4965 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004969
4970 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971
William Lallemand0f99e342011-10-12 17:50:54 +02004972 logsrv->facility = get_log_facility(args[2]);
4973 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
4977
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
4979
William Lallemand0f99e342011-10-12 17:50:54 +02004980 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004982 logsrv->level = get_log_level(args[3]);
4983 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 }
4990
William Lallemand0f99e342011-10-12 17:50:54 +02004991 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004992 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004993 logsrv->minlvl = get_log_level(args[4]);
4994 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004995 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
4998
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004999 }
5000 }
5001
Robert Tsai81ae1952007-12-05 10:47:29 +01005002 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01005003 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005004 if (!sk) {
5005 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01005006 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
William Lallemand0f99e342011-10-12 17:50:54 +02005010 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01005011 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005012 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01005013 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01005014 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
William Lallemand0f99e342011-10-12 17:50:54 +02005018 logsrv->addr = *sk;
5019 if (!get_host_port(&logsrv->addr))
5020 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
William Lallemand0f99e342011-10-12 17:50:54 +02005022
5023 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
5025 else {
5026 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5027 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 }
5032 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005033 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005034 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005035
Willy Tarreau977b8e42006-12-29 14:19:17 +01005036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005038
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005040 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5041 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005045
5046 /* we must first clear any optional default setting */
5047 curproxy->options &= ~PR_O_TPXY_MASK;
5048 free(curproxy->iface_name);
5049 curproxy->iface_name = NULL;
5050 curproxy->iface_len = 0;
5051
Willy Tarreaud5191e72010-02-09 20:50:45 +01005052 sk = str2sa(args[1]);
5053 if (!sk) {
5054 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060
5061 cur_arg = 2;
5062 while (*(args[cur_arg])) {
5063 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005064#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5065#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5067 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5068 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071 }
5072#endif
5073 if (!*args[cur_arg + 1]) {
5074 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5075 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005078 }
5079
5080 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005081 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005082 curproxy->options |= PR_O_TPXY_CLI;
5083 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005084 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005085 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005086 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5087 char *name, *end;
5088
5089 name = args[cur_arg+1] + 7;
5090 while (isspace(*name))
5091 name++;
5092
5093 end = name;
5094 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5095 end++;
5096
5097 curproxy->options &= ~PR_O_TPXY_MASK;
5098 curproxy->options |= PR_O_TPXY_DYN;
5099 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5100 curproxy->bind_hdr_len = end - name;
5101 memcpy(curproxy->bind_hdr_name, name, end - name);
5102 curproxy->bind_hdr_name[end-name] = '\0';
5103 curproxy->bind_hdr_occ = -1;
5104
5105 /* now look for an occurrence number */
5106 while (isspace(*end))
5107 end++;
5108 if (*end == ',') {
5109 end++;
5110 name = end;
5111 if (*end == '-')
5112 end++;
5113 while (isdigit(*end))
5114 end++;
5115 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5116 }
5117
5118 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5119 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5120 " occurrences values smaller than %d.\n",
5121 file, linenum, MAX_HDR_HISTORY);
5122 err_code |= ERR_ALERT | ERR_FATAL;
5123 goto out;
5124 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005126 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005127 if (!sk) {
5128 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005133 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005134 }
5135 global.last_checks |= LSTCHK_NETADM;
5136#if !defined(CONFIG_HAP_LINUX_TPROXY)
5137 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005138#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005139#else /* no TPROXY support */
5140 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005141 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005144#endif
5145 cur_arg += 2;
5146 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005147 }
5148
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005149 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5150#ifdef SO_BINDTODEVICE
5151 if (!*args[cur_arg + 1]) {
5152 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005156 }
5157 if (curproxy->iface_name)
5158 free(curproxy->iface_name);
5159
5160 curproxy->iface_name = strdup(args[cur_arg + 1]);
5161 curproxy->iface_len = strlen(curproxy->iface_name);
5162 global.last_checks |= LSTCHK_NETADM;
5163#else
5164 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5165 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005168#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005169 cur_arg += 2;
5170 continue;
5171 }
5172 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5173 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005178 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5179 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5180 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5187 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191
5192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005193 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005194 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005200 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
5205 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005207 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 }
5212 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005214 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005215 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005221 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005222 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005226 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005228 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005229 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005231 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005232 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005233 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005235 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005236 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005238 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005239 }
5240 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005242 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005243 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005244 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005245 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254
5255 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005256 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005257 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
5261 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005263 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005264 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
5268 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005270 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005271 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005277 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005278 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
5282 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005284 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005285 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005289 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005291 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005297 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005298
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 if (curproxy == &defproxy) {
5300 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005304 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 if (*(args[1]) == 0) {
5308 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005312
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005313 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005314 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5315 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5316 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5321 }
5322 else if (*args[2]) {
5323 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5324 file, linenum, args[0], args[2]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
5328
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005329 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005330 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005331 wl->s = strdup(args[1]);
5332 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005333 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005342
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005344 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005345 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
5349 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005351 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
5356 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005357 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005358 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005359 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005364 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370
Willy Tarreauade5ec42010-01-28 19:33:49 +01005371 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005372 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005373 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005374 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
5377 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005378 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005379 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005380 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005381 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005385 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005386 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005387 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005392 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005393
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 if (curproxy == &defproxy) {
5395 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005399 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401
Willy Tarreaubaaee002006-06-26 02:48:02 +02005402 if (*(args[1]) == 0) {
5403 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 }
5407
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005408 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005409 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5410 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5411 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
5414 }
5415 err_code |= warnif_cond_requires_req(cond, file, linenum);
5416 }
5417 else if (*args[2]) {
5418 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5419 file, linenum, args[0], args[2]);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
5423
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005424 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005425 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005426 wl->s = strdup(args[1]);
5427 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 }
5429 else if (!strcmp(args[0], "errorloc") ||
5430 !strcmp(args[0], "errorloc302") ||
5431 !strcmp(args[0], "errorloc303")) { /* error location */
5432 int errnum, errlen;
5433 char *err;
5434
Willy Tarreau977b8e42006-12-29 14:19:17 +01005435 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005436 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005437
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005439 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443
5444 errnum = atol(args[1]);
5445 if (!strcmp(args[0], "errorloc303")) {
5446 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5447 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5448 } else {
5449 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5450 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5451 }
5452
Willy Tarreau0f772532006-12-23 20:51:41 +01005453 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5454 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005455 chunk_destroy(&curproxy->errmsg[rc]);
5456 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005457 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005460
5461 if (rc >= HTTP_ERR_SIZE) {
5462 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5463 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 free(err);
5465 }
5466 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005467 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5468 int errnum, errlen, fd;
5469 char *err;
5470 struct stat stat;
5471
5472 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005474
5475 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005476 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005479 }
5480
5481 fd = open(args[2], O_RDONLY);
5482 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5483 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5484 file, linenum, args[2], args[1]);
5485 if (fd >= 0)
5486 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005487 err_code |= ERR_ALERT | ERR_FATAL;
5488 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005489 }
5490
Willy Tarreau27a674e2009-08-17 07:23:33 +02005491 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005492 errlen = stat.st_size;
5493 } else {
5494 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005495 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005496 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005497 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005498 }
5499
5500 err = malloc(errlen); /* malloc() must succeed during parsing */
5501 errnum = read(fd, err, errlen);
5502 if (errnum != errlen) {
5503 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5504 file, linenum, args[2], args[1]);
5505 close(fd);
5506 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005509 }
5510 close(fd);
5511
5512 errnum = atol(args[1]);
5513 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5514 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005515 chunk_destroy(&curproxy->errmsg[rc]);
5516 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005517 break;
5518 }
5519 }
5520
5521 if (rc >= HTTP_ERR_SIZE) {
5522 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5523 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005524 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005525 free(err);
5526 }
5527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005529 struct cfg_kw_list *kwl;
5530 int index;
5531
5532 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5533 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5534 if (kwl->kw[index].section != CFG_LISTEN)
5535 continue;
5536 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5537 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005538 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005539 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005540 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005541 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005542 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005545 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005546 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005547 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 err_code |= ERR_WARN;
5549 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005550 }
Willy Tarreau93893792009-07-23 13:19:11 +02005551 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005552 }
5553 }
5554 }
5555
Willy Tarreau6daf3432008-01-22 16:44:08 +01005556 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 }
Willy Tarreau93893792009-07-23 13:19:11 +02005560 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005561 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005562 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563}
5564
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005565int
5566cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5567{
5568
5569 int err_code = 0;
5570 const char *err;
5571
5572 if (!strcmp(args[0], "userlist")) { /* new userlist */
5573 struct userlist *newul;
5574
5575 if (!*args[1]) {
5576 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5577 file, linenum, args[0]);
5578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
5580 }
5581
5582 err = invalid_char(args[1]);
5583 if (err) {
5584 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5585 file, linenum, *err, args[0], args[1]);
5586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
5588 }
5589
5590 for (newul = userlist; newul; newul = newul->next)
5591 if (!strcmp(newul->name, args[1])) {
5592 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5593 file, linenum, args[1]);
5594 err_code |= ERR_WARN;
5595 goto out;
5596 }
5597
5598 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5599 if (!newul) {
5600 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5601 err_code |= ERR_ALERT | ERR_ABORT;
5602 goto out;
5603 }
5604
5605 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5606 newul->name = strdup(args[1]);
5607
5608 if (!newul->groupusers | !newul->name) {
5609 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5610 err_code |= ERR_ALERT | ERR_ABORT;
5611 goto out;
5612 }
5613
5614 newul->next = userlist;
5615 userlist = newul;
5616
5617 } else if (!strcmp(args[0], "group")) { /* new group */
5618 int cur_arg, i;
5619 const char *err;
5620
5621 if (!*args[1]) {
5622 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5623 file, linenum, args[0]);
5624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
5626 }
5627
5628 err = invalid_char(args[1]);
5629 if (err) {
5630 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5631 file, linenum, *err, args[0], args[1]);
5632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
5635
5636 for(i = 0; i < userlist->grpcnt; i++)
5637 if (!strcmp(userlist->groups[i], args[1])) {
5638 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5639 file, linenum, args[1], userlist->name);
5640 err_code |= ERR_ALERT;
5641 goto out;
5642 }
5643
5644 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5645 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5646 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650
5651 cur_arg = 2;
5652
5653 while (*args[cur_arg]) {
5654 if (!strcmp(args[cur_arg], "users")) {
5655 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5656 cur_arg += 2;
5657 continue;
5658 } else {
5659 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5660 file, linenum, args[0]);
5661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
5663 }
5664 }
5665
5666 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5667 } else if (!strcmp(args[0], "user")) { /* new user */
5668 struct auth_users *newuser;
5669 int cur_arg;
5670
5671 if (!*args[1]) {
5672 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5673 file, linenum, args[0]);
5674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
5677
5678 for (newuser = userlist->users; newuser; newuser = newuser->next)
5679 if (!strcmp(newuser->user, args[1])) {
5680 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5681 file, linenum, args[1], userlist->name);
5682 err_code |= ERR_ALERT;
5683 goto out;
5684 }
5685
5686 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5687 if (!newuser) {
5688 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5689 err_code |= ERR_ALERT | ERR_ABORT;
5690 goto out;
5691 }
5692
5693 newuser->user = strdup(args[1]);
5694
5695 newuser->next = userlist->users;
5696 userlist->users = newuser;
5697
5698 cur_arg = 2;
5699
5700 while (*args[cur_arg]) {
5701 if (!strcmp(args[cur_arg], "password")) {
5702#ifndef CONFIG_HAP_CRYPT
5703 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5704 file, linenum);
5705 err_code |= ERR_ALERT;
5706#endif
5707 newuser->pass = strdup(args[cur_arg + 1]);
5708 cur_arg += 2;
5709 continue;
5710 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5711 newuser->pass = strdup(args[cur_arg + 1]);
5712 newuser->flags |= AU_O_INSECURE;
5713 cur_arg += 2;
5714 continue;
5715 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005716 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005717 cur_arg += 2;
5718 continue;
5719 } else {
5720 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5721 file, linenum, args[0]);
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
5725 }
5726 } else {
5727 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5728 err_code |= ERR_ALERT | ERR_FATAL;
5729 }
5730
5731out:
5732 return err_code;
5733}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734
5735/*
5736 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005737 * Returns the error code, 0 if OK, or any combination of :
5738 * - ERR_ABORT: must abort ASAP
5739 * - ERR_FATAL: we can continue parsing but not start the service
5740 * - ERR_WARN: a warning has been emitted
5741 * - ERR_ALERT: an alert has been emitted
5742 * Only the two first ones can stop processing, the two others are just
5743 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005745int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005747 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 FILE *f;
5749 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005751 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 if ((f=fopen(file,"r")) == NULL)
5754 return -1;
5755
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005756 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005757 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005758 char *end;
5759 char *args[MAX_LINE_ARGS + 1];
5760 char *line = thisline;
5761
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 linenum++;
5763
5764 end = line + strlen(line);
5765
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005766 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5767 /* Check if we reached the limit and the last char is not \n.
5768 * Watch out for the last line without the terminating '\n'!
5769 */
5770 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005771 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005772 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005773 }
5774
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005776 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 line++;
5778
5779 arg = 0;
5780 args[arg] = line;
5781
5782 while (*line && arg < MAX_LINE_ARGS) {
5783 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5784 * C equivalent value. Other combinations left unchanged (eg: \1).
5785 */
5786 if (*line == '\\') {
5787 int skip = 0;
5788 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5789 *line = line[1];
5790 skip = 1;
5791 }
5792 else if (line[1] == 'r') {
5793 *line = '\r';
5794 skip = 1;
5795 }
5796 else if (line[1] == 'n') {
5797 *line = '\n';
5798 skip = 1;
5799 }
5800 else if (line[1] == 't') {
5801 *line = '\t';
5802 skip = 1;
5803 }
5804 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005805 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 unsigned char hex1, hex2;
5807 hex1 = toupper(line[2]) - '0';
5808 hex2 = toupper(line[3]) - '0';
5809 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5810 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5811 *line = (hex1<<4) + hex2;
5812 skip = 3;
5813 }
5814 else {
5815 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005816 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 }
5818 }
5819 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005820 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 end -= skip;
5822 }
5823 line++;
5824 }
5825 else if (*line == '#' || *line == '\n' || *line == '\r') {
5826 /* end of string, end of loop */
5827 *line = 0;
5828 break;
5829 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005830 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005832 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005833 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 line++;
5835 args[++arg] = line;
5836 }
5837 else {
5838 line++;
5839 }
5840 }
5841
5842 /* empty line */
5843 if (!**args)
5844 continue;
5845
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005846 if (*line) {
5847 /* we had to stop due to too many args.
5848 * Let's terminate the string, print the offending part then cut the
5849 * last arg.
5850 */
5851 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5852 line++;
5853 *line = '\0';
5854
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005855 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005856 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 args[arg] = line;
5859 }
5860
Willy Tarreau540abe42007-05-02 20:50:16 +02005861 /* zero out remaining args and ensure that at least one entry
5862 * is zeroed out.
5863 */
5864 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 args[arg] = line;
5866 }
5867
Willy Tarreau3842f002009-06-14 11:39:52 +02005868 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005869 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005870 char *tmp;
5871
Willy Tarreau3842f002009-06-14 11:39:52 +02005872 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005873 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005874 for (arg=0; *args[arg+1]; arg++)
5875 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005876 *tmp = '\0'; // fix the next arg to \0
5877 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005878 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005879 else if (!strcmp(args[0], "default")) {
5880 kwm = KWM_DEF;
5881 for (arg=0; *args[arg+1]; arg++)
5882 args[arg] = args[arg+1]; // shift args after inversion
5883 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005884
William Lallemand0f99e342011-10-12 17:50:54 +02005885 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5886 strcmp(args[0], "log") != 0) {
5887 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005888 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005889 }
5890
Willy Tarreau977b8e42006-12-29 14:19:17 +01005891 if (!strcmp(args[0], "listen") ||
5892 !strcmp(args[0], "frontend") ||
5893 !strcmp(args[0], "backend") ||
5894 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005895 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005897 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005898 cursection = strdup(args[0]);
5899 }
5900 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005902 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005903 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005904 }
5905 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005906 confsect = CFG_USERLIST;
5907 free(cursection);
5908 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005909 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005910 else if (!strcmp(args[0], "peers")) {
5911 confsect = CFG_PEERS;
5912 free(cursection);
5913 cursection = strdup(args[0]);
5914 }
5915
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 /* else it's a section keyword */
5917
5918 switch (confsect) {
5919 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005920 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 break;
5922 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005923 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005925 case CFG_USERLIST:
5926 err_code |= cfg_parse_users(file, linenum, args, kwm);
5927 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005928 case CFG_PEERS:
5929 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5930 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005932 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005933 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005934 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005935
5936 if (err_code & ERR_ABORT)
5937 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005939 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005940 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005942 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005943}
5944
Willy Tarreaubb925012009-07-23 13:36:36 +02005945/*
5946 * Returns the error code, 0 if OK, or any combination of :
5947 * - ERR_ABORT: must abort ASAP
5948 * - ERR_FATAL: we can continue parsing but not start the service
5949 * - ERR_WARN: a warning has been emitted
5950 * - ERR_ALERT: an alert has been emitted
5951 * Only the two first ones can stop processing, the two others are just
5952 * indicators.
5953 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005954int check_config_validity()
5955{
5956 int cfgerr = 0;
5957 struct proxy *curproxy = NULL;
5958 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005959 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005960 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005961 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962
5963 /*
5964 * Now, check for the integrity of all that we have collected.
5965 */
5966
5967 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005968 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005970 /* first, we will invert the proxy list order */
5971 curproxy = NULL;
5972 while (proxy) {
5973 struct proxy *next;
5974
5975 next = proxy->next;
5976 proxy->next = curproxy;
5977 curproxy = proxy;
5978 if (!next)
5979 break;
5980 proxy = next;
5981 }
5982
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005984 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005985 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005987 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005988 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005989 unsigned int next_id;
5990
5991 if (!curproxy->uuid) {
5992 /* proxy ID not set, use automatic numbering with first
5993 * spare entry starting with next_pxid.
5994 */
5995 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5996 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5997 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005998 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005999 next_pxid++;
6000
Willy Tarreau55ea7572007-06-17 19:56:27 +02006001
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006003 /* ensure we don't keep listeners uselessly bound */
6004 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 curproxy = curproxy->next;
6006 continue;
6007 }
6008
Willy Tarreauff01a212009-03-15 13:46:16 +01006009 switch (curproxy->mode) {
6010 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006011 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006012 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006015 cfgerr++;
6016 }
6017
6018 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006019 Warning("config : servers will be ignored for %s '%s'.\n",
6020 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006021 break;
6022
6023 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006024 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006025 break;
6026
6027 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006028 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006029 break;
6030 }
6031
6032 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006033 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
6034 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 cfgerr++;
6036 }
Willy Tarreauff01a212009-03-15 13:46:16 +01006037
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006038 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006039 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006040 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006041 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6042 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006043 cfgerr++;
6044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006046 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006047 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6048 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006049 cfgerr++;
6050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006051#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006052 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006053 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6054 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006055 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006056 }
6057 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006058 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006059 /* If no LB algo is set in a backend, and we're not in
6060 * transparent mode, dispatch mode nor proxy mode, we
6061 * want to use balance roundrobin by default.
6062 */
6063 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6064 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 }
6066 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006067
Willy Tarreau1620ec32011-08-06 17:05:02 +02006068 if (curproxy->options & PR_O_DISPATCH)
6069 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6070 else if (curproxy->options & PR_O_HTTP_PROXY)
6071 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6072 else if (curproxy->options & PR_O_TRANSP)
6073 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006074
Willy Tarreau1620ec32011-08-06 17:05:02 +02006075 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6076 if (curproxy->options & PR_O_DISABLE404) {
6077 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6078 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6079 err_code |= ERR_WARN;
6080 curproxy->options &= ~PR_O_DISABLE404;
6081 }
6082 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6083 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6084 "send-state", proxy_type_str(curproxy), curproxy->id);
6085 err_code |= ERR_WARN;
6086 curproxy->options &= ~PR_O2_CHK_SNDST;
6087 }
Willy Tarreauef781042010-01-27 11:53:01 +01006088 }
6089
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006090 /* if a default backend was specified, let's find it */
6091 if (curproxy->defbe.name) {
6092 struct proxy *target;
6093
Alex Williams96532db2009-11-01 21:27:13 -05006094 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006095 if (!target) {
6096 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6097 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006098 cfgerr++;
6099 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006100 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6101 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006102 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006103 } else {
6104 free(curproxy->defbe.name);
6105 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006106 /* we force the backend to be present on at least all of
6107 * the frontend's processes.
6108 */
6109 target->bind_proc = curproxy->bind_proc ?
6110 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006111
6112 /* Emit a warning if this proxy also has some servers */
6113 if (curproxy->srv) {
6114 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6115 curproxy->id);
6116 err_code |= ERR_WARN;
6117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006118 }
6119 }
6120
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006121 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006122 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6123 /* map jump target for ACT_SETBE in req_rep chain */
6124 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006125 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006126 struct proxy *target;
6127
Willy Tarreaua496b602006-12-17 23:15:24 +01006128 if (exp->action != ACT_SETBE)
6129 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006130
Alex Williams96532db2009-11-01 21:27:13 -05006131 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006132 if (!target) {
6133 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6134 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006135 cfgerr++;
6136 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006137 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6138 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006139 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006140 } else {
6141 free((void *)exp->replace);
6142 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006143 /* we force the backend to be present on at least all of
6144 * the frontend's processes.
6145 */
6146 target->bind_proc = curproxy->bind_proc ?
6147 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006148 }
6149 }
6150 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006151
6152 /* find the target proxy for 'use_backend' rules */
6153 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006154 struct proxy *target;
6155
Alex Williams96532db2009-11-01 21:27:13 -05006156 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006157
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006158 if (!target) {
6159 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6160 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006161 cfgerr++;
6162 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006163 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6164 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006165 cfgerr++;
6166 } else {
6167 free((void *)rule->be.name);
6168 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006169 /* we force the backend to be present on at least all of
6170 * the frontend's processes.
6171 */
6172 target->bind_proc = curproxy->bind_proc ?
6173 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006174 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006175 }
6176
6177 /* find the target proxy for 'use_backend' rules */
6178 list_for_each_entry(srule, &curproxy->server_rules, list) {
6179 struct server *target = findserver(curproxy, srule->srv.name);
6180
6181 if (!target) {
6182 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6183 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6184 cfgerr++;
6185 continue;
6186 }
6187 free((void *)srule->srv.name);
6188 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006189 }
6190
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 /* find the target table for 'stick' rules */
6192 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6193 struct proxy *target;
6194
Emeric Brun1d33b292010-01-04 15:47:17 +01006195 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6196 if (mrule->flags & STK_IS_STORE)
6197 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6198
Emeric Brunb982a3d2010-01-04 15:45:53 +01006199 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006200 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006201 else
6202 target = curproxy;
6203
6204 if (!target) {
6205 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6206 curproxy->id, mrule->table.name);
6207 cfgerr++;
6208 }
6209 else if (target->table.size == 0) {
6210 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6211 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6212 cfgerr++;
6213 }
Willy Tarreau12785782012-04-27 21:37:17 +02006214 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6215 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006216 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6217 cfgerr++;
6218 }
6219 else {
6220 free((void *)mrule->table.name);
6221 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006222 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006223 }
6224 }
6225
6226 /* find the target table for 'store response' rules */
6227 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6228 struct proxy *target;
6229
Emeric Brun1d33b292010-01-04 15:47:17 +01006230 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6231
Emeric Brunb982a3d2010-01-04 15:45:53 +01006232 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006233 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006234 else
6235 target = curproxy;
6236
6237 if (!target) {
6238 Alert("Proxy '%s': unable to find store table '%s'.\n",
6239 curproxy->id, mrule->table.name);
6240 cfgerr++;
6241 }
6242 else if (target->table.size == 0) {
6243 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6244 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6245 cfgerr++;
6246 }
Willy Tarreau12785782012-04-27 21:37:17 +02006247 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6248 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006249 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6250 cfgerr++;
6251 }
6252 else {
6253 free((void *)mrule->table.name);
6254 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006255 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006256 }
6257 }
6258
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006259 /* find the target table for 'tcp-request' layer 4 rules */
6260 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6261 struct proxy *target;
6262
Willy Tarreau56123282010-08-06 19:06:56 +02006263 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006264 continue;
6265
6266 if (trule->act_prm.trk_ctr.table.n)
6267 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6268 else
6269 target = curproxy;
6270
6271 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006272 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6273 curproxy->id, trule->act_prm.trk_ctr.table.n,
6274 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006275 cfgerr++;
6276 }
6277 else if (target->table.size == 0) {
6278 Alert("Proxy '%s': table '%s' used but not configured.\n",
6279 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6280 cfgerr++;
6281 }
6282 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006283 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006284 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6285 cfgerr++;
6286 }
6287 else {
6288 free(trule->act_prm.trk_ctr.table.n);
6289 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006290 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006291 * to pass a list of counters to track and allocate them right here using
6292 * stktable_alloc_data_type().
6293 */
6294 }
6295 }
6296
Willy Tarreaud1f96522010-08-03 19:34:32 +02006297 /* find the target table for 'tcp-request' layer 6 rules */
6298 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6299 struct proxy *target;
6300
Willy Tarreau56123282010-08-06 19:06:56 +02006301 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006302 continue;
6303
6304 if (trule->act_prm.trk_ctr.table.n)
6305 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6306 else
6307 target = curproxy;
6308
6309 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006310 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6311 curproxy->id, trule->act_prm.trk_ctr.table.n,
6312 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006313 cfgerr++;
6314 }
6315 else if (target->table.size == 0) {
6316 Alert("Proxy '%s': table '%s' used but not configured.\n",
6317 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6318 cfgerr++;
6319 }
6320 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006321 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006322 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6323 cfgerr++;
6324 }
6325 else {
6326 free(trule->act_prm.trk_ctr.table.n);
6327 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006328 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006329 * to pass a list of counters to track and allocate them right here using
6330 * stktable_alloc_data_type().
6331 */
6332 }
6333 }
6334
Emeric Brun32da3c42010-09-23 18:39:19 +02006335 if (curproxy->table.peers.name) {
6336 struct peers *curpeers = peers;
6337
6338 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6339 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6340 free((void *)curproxy->table.peers.name);
6341 curproxy->table.peers.p = peers;
6342 break;
6343 }
6344 }
6345
6346 if (!curpeers) {
6347 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6348 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006349 free((void *)curproxy->table.peers.name);
6350 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006351 cfgerr++;
6352 }
6353 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006354 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6355 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006356 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006357 cfgerr++;
6358 }
6359 }
6360
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006361 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006362 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006363 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6364 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6365 "proxy", curproxy->id);
6366 cfgerr++;
6367 goto out_uri_auth_compat;
6368 }
6369
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006370 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006371 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006372 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006373 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006374
Willy Tarreau95fa4692010-02-01 13:05:50 +01006375 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6376 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006377
6378 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006379 uri_auth_compat_req[i++] = "realm";
6380 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6381 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006382
Willy Tarreau95fa4692010-02-01 13:05:50 +01006383 uri_auth_compat_req[i++] = "unless";
6384 uri_auth_compat_req[i++] = "{";
6385 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6386 uri_auth_compat_req[i++] = "}";
6387 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006388
Willy Tarreauff011f22011-01-06 17:51:27 +01006389 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6390 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006391 cfgerr++;
6392 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006393 }
6394
Willy Tarreauff011f22011-01-06 17:51:27 +01006395 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006396
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006397 if (curproxy->uri_auth->auth_realm) {
6398 free(curproxy->uri_auth->auth_realm);
6399 curproxy->uri_auth->auth_realm = NULL;
6400 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006401
6402 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006403 }
6404out_uri_auth_compat:
6405
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006406 cfgerr += acl_find_targets(curproxy);
6407
Willy Tarreau2738a142006-07-08 17:28:09 +02006408 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006409 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006410 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006411 (!curproxy->timeout.connect ||
6412 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006413 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006414 " | While not properly invalid, you will certainly encounter various problems\n"
6415 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006416 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006417 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006418 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006419 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006420
Willy Tarreau1fa31262007-12-03 00:36:16 +01006421 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6422 * We must still support older configurations, so let's find out whether those
6423 * parameters have been set or must be copied from contimeouts.
6424 */
6425 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006426 if (!curproxy->timeout.tarpit ||
6427 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006428 /* tarpit timeout not set. We search in the following order:
6429 * default.tarpit, curr.connect, default.connect.
6430 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006431 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006432 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006433 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006434 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006435 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006436 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006437 }
6438 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006439 (!curproxy->timeout.queue ||
6440 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006441 /* queue timeout not set. We search in the following order:
6442 * default.queue, curr.connect, default.connect.
6443 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006444 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006445 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006446 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006447 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006448 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006449 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006450 }
6451 }
6452
Willy Tarreau1620ec32011-08-06 17:05:02 +02006453 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006454 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6455 curproxy->check_req = (char *)malloc(curproxy->check_len);
6456 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006457 }
6458
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006459 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006460 if (curproxy->nb_req_cap) {
6461 if (curproxy->mode == PR_MODE_HTTP) {
6462 curproxy->req_cap_pool = create_pool("ptrcap",
6463 curproxy->nb_req_cap * sizeof(char *),
6464 MEM_F_SHARED);
6465 } else {
6466 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6467 proxy_type_str(curproxy), curproxy->id);
6468 err_code |= ERR_WARN;
6469 curproxy->to_log &= ~LW_REQHDR;
6470 curproxy->nb_req_cap = 0;
6471 }
6472 }
6473
6474 if (curproxy->nb_rsp_cap) {
6475 if (curproxy->mode == PR_MODE_HTTP) {
6476 curproxy->rsp_cap_pool = create_pool("ptrcap",
6477 curproxy->nb_rsp_cap * sizeof(char *),
6478 MEM_F_SHARED);
6479 } else {
6480 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6481 proxy_type_str(curproxy), curproxy->id);
6482 err_code |= ERR_WARN;
6483 curproxy->to_log &= ~LW_REQHDR;
6484 curproxy->nb_rsp_cap = 0;
6485 }
6486 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006487
Willy Tarreau196729e2012-05-31 19:30:26 +02006488 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006489 if (!(curproxy->cap & PR_CAP_FE)) {
6490 if (curproxy->logformat_string != default_http_log_format &&
6491 curproxy->logformat_string != default_tcp_log_format &&
6492 curproxy->logformat_string != clf_http_log_format)
6493 free(curproxy->logformat_string);
6494 curproxy->logformat_string = NULL;
6495 }
6496
Willy Tarreau196729e2012-05-31 19:30:26 +02006497 if (curproxy->logformat_string)
6498 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6499
6500 if (curproxy->uniqueid_format_string)
6501 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6502
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 /* first, we will invert the servers list order */
6504 newsrv = NULL;
6505 while (curproxy->srv) {
6506 struct server *next;
6507
6508 next = curproxy->srv->next;
6509 curproxy->srv->next = newsrv;
6510 newsrv = curproxy->srv;
6511 if (!next)
6512 break;
6513 curproxy->srv = next;
6514 }
6515
Willy Tarreaudd701652010-05-25 23:03:02 +02006516 /* assign automatic UIDs to servers which don't have one yet */
6517 next_id = 1;
6518 newsrv = curproxy->srv;
6519 while (newsrv != NULL) {
6520 if (!newsrv->puid) {
6521 /* server ID not set, use automatic numbering with first
6522 * spare entry starting with next_svid.
6523 */
6524 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6525 newsrv->conf.id.key = newsrv->puid = next_id;
6526 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6527 }
6528 next_id++;
6529 newsrv = newsrv->next;
6530 }
6531
Willy Tarreau20697042007-11-15 23:26:18 +01006532 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006533 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534
Willy Tarreau62c3be22012-01-20 13:12:32 +01006535 /*
6536 * If this server supports a maxconn parameter, it needs a dedicated
6537 * tasks to fill the emptied slots when a connection leaves.
6538 * Also, resolve deferred tracking dependency if needed.
6539 */
6540 newsrv = curproxy->srv;
6541 while (newsrv != NULL) {
6542 if (newsrv->minconn > newsrv->maxconn) {
6543 /* Only 'minconn' was specified, or it was higher than or equal
6544 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6545 * this will avoid further useless expensive computations.
6546 */
6547 newsrv->maxconn = newsrv->minconn;
6548 } else if (newsrv->maxconn && !newsrv->minconn) {
6549 /* minconn was not specified, so we set it to maxconn */
6550 newsrv->minconn = newsrv->maxconn;
6551 }
6552
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006553#ifdef USE_OPENSSL
6554#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6555#define SSL_OP_NO_COMPRESSION 0
6556#endif
6557#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6558#define SSL_MODE_RELEASE_BUFFERS 0
6559#endif
6560#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6561#define SSL_OP_NO_COMPRESSION 0
6562#endif
6563 if (newsrv->use_ssl) {
6564 int ssloptions =
6565 SSL_OP_ALL | /* all known workarounds for bugs */
6566 SSL_OP_NO_SSLv2 |
6567 SSL_OP_NO_COMPRESSION;
6568 int sslmode =
6569 SSL_MODE_ENABLE_PARTIAL_WRITE |
6570 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6571 SSL_MODE_RELEASE_BUFFERS;
6572
6573 /* Initiate SSL context for current server */
6574 newsrv->ssl_ctx.reused_sess = NULL;
6575 newsrv->data = &ssl_sock;
6576 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6577 if(!newsrv->ssl_ctx.ctx) {
6578
6579 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6580 proxy_type_str(curproxy), curproxy->id,
6581 newsrv->id);
6582 cfgerr++;
6583 goto next_srv;
6584 }
6585
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006586 if (newsrv->ssl_ctx.nosslv3)
6587 ssloptions |= SSL_OP_NO_SSLv3;
6588 if (newsrv->ssl_ctx.notlsv1)
6589 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006590 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6591 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6592 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6593 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006594 if (newsrv->ssl_ctx.ciphers &&
6595 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6596 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6597 curproxy->id, newsrv->id,
6598 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6599 cfgerr++;
6600 goto next_srv;
6601 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006602 }
6603#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006604 if (newsrv->trackit) {
6605 struct proxy *px;
6606 struct server *srv;
6607 char *pname, *sname;
6608
6609 pname = newsrv->trackit;
6610 sname = strrchr(pname, '/');
6611
6612 if (sname)
6613 *sname++ = '\0';
6614 else {
6615 sname = pname;
6616 pname = NULL;
6617 }
6618
6619 if (pname) {
6620 px = findproxy(pname, PR_CAP_BE);
6621 if (!px) {
6622 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6623 proxy_type_str(curproxy), curproxy->id,
6624 newsrv->id, pname);
6625 cfgerr++;
6626 goto next_srv;
6627 }
6628 } else
6629 px = curproxy;
6630
6631 srv = findserver(px, sname);
6632 if (!srv) {
6633 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6634 proxy_type_str(curproxy), curproxy->id,
6635 newsrv->id, sname);
6636 cfgerr++;
6637 goto next_srv;
6638 }
6639
6640 if (!(srv->state & SRV_CHECKED)) {
6641 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6642 "tracking as it does not have checks enabled.\n",
6643 proxy_type_str(curproxy), curproxy->id,
6644 newsrv->id, px->id, srv->id);
6645 cfgerr++;
6646 goto next_srv;
6647 }
6648
6649 if (curproxy != px &&
6650 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6651 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6652 "tracking: disable-on-404 option inconsistency.\n",
6653 proxy_type_str(curproxy), curproxy->id,
6654 newsrv->id, px->id, srv->id);
6655 cfgerr++;
6656 goto next_srv;
6657 }
6658
6659 /* if the other server is forced disabled, we have to do the same here */
6660 if (srv->state & SRV_MAINTAIN) {
6661 newsrv->state |= SRV_MAINTAIN;
6662 newsrv->state &= ~SRV_RUNNING;
6663 newsrv->health = 0;
6664 }
6665
6666 newsrv->track = srv;
6667 newsrv->tracknext = srv->tracknext;
6668 srv->tracknext = newsrv;
6669
6670 free(newsrv->trackit);
6671 newsrv->trackit = NULL;
6672 }
6673 next_srv:
6674 newsrv = newsrv->next;
6675 }
6676
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006677 /* We have to initialize the server lookup mechanism depending
6678 * on what LB algorithm was choosen.
6679 */
6680
6681 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6682 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6683 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006684 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6685 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6686 init_server_map(curproxy);
6687 } else {
6688 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6689 fwrr_init_server_groups(curproxy);
6690 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006691 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006692
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006693 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006694 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6695 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6696 fwlc_init_server_tree(curproxy);
6697 } else {
6698 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6699 fas_init_server_tree(curproxy);
6700 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006701 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006702
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006703 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006704 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6705 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6706 chash_init_server_tree(curproxy);
6707 } else {
6708 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6709 init_server_map(curproxy);
6710 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006711 break;
6712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713
6714 if (curproxy->options & PR_O_LOGASAP)
6715 curproxy->to_log &= ~LW_BYTES;
6716
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006717 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006718 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006719 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6720 proxy_type_str(curproxy), curproxy->id);
6721 err_code |= ERR_WARN;
6722 }
6723
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006724 if (curproxy->mode != PR_MODE_HTTP) {
6725 int optnum;
6726
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006727 if (curproxy->uri_auth) {
6728 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6729 proxy_type_str(curproxy), curproxy->id);
6730 err_code |= ERR_WARN;
6731 curproxy->uri_auth = NULL;
6732 }
6733
Willy Tarreau87cf5142011-08-19 22:57:24 +02006734 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006735 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6736 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6737 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006738 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006739 }
6740
6741 if (curproxy->options & PR_O_ORGTO) {
6742 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6743 "originalto", proxy_type_str(curproxy), curproxy->id);
6744 err_code |= ERR_WARN;
6745 curproxy->options &= ~PR_O_ORGTO;
6746 }
6747
6748 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6749 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6750 (curproxy->cap & cfg_opts[optnum].cap) &&
6751 (curproxy->options & cfg_opts[optnum].val)) {
6752 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6753 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6754 err_code |= ERR_WARN;
6755 curproxy->options &= ~cfg_opts[optnum].val;
6756 }
6757 }
6758
6759 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6760 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6761 (curproxy->cap & cfg_opts2[optnum].cap) &&
6762 (curproxy->options2 & cfg_opts2[optnum].val)) {
6763 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6764 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6765 err_code |= ERR_WARN;
6766 curproxy->options2 &= ~cfg_opts2[optnum].val;
6767 }
6768 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006769
Willy Tarreauefa5f512010-03-30 20:13:29 +02006770#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006771 if (curproxy->bind_hdr_occ) {
6772 curproxy->bind_hdr_occ = 0;
6773 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6774 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6775 err_code |= ERR_WARN;
6776 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006777#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006778 }
6779
Willy Tarreaubaaee002006-06-26 02:48:02 +02006780 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006781 * ensure that we're not cross-dressing a TCP server into HTTP.
6782 */
6783 newsrv = curproxy->srv;
6784 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006785 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006786 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6787 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006788 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006789 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006790
Willy Tarreau0cec3312011-10-31 13:49:26 +01006791 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6792 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6793 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6794 err_code |= ERR_WARN;
6795 }
6796
Willy Tarreauefa5f512010-03-30 20:13:29 +02006797#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006798 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6799 newsrv->bind_hdr_occ = 0;
6800 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6801 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6802 err_code |= ERR_WARN;
6803 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006804#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006805 newsrv = newsrv->next;
6806 }
6807
Willy Tarreauc1a21672009-08-16 22:37:44 +02006808 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006809 curproxy->accept = frontend_accept;
6810
Willy Tarreauc1a21672009-08-16 22:37:44 +02006811 if (curproxy->tcp_req.inspect_delay ||
6812 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006813 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006814
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006815 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006816 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006817 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006818 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006819
6820 /* both TCP and HTTP must check switching rules */
6821 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6822 }
6823
6824 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006825 if (curproxy->tcp_req.inspect_delay ||
6826 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6827 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6828
Emeric Brun97679e72010-09-23 17:56:44 +02006829 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6830 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6831
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006832 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006833 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006834 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006835 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006836
6837 /* If the backend does requires RDP cookie persistence, we have to
6838 * enable the corresponding analyser.
6839 */
6840 if (curproxy->options2 & PR_O2_RDPC_PRST)
6841 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6842 }
6843
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006844 listener = NULL;
6845 while (curproxy->listen) {
6846 struct listener *next;
6847
6848 next = curproxy->listen->next;
6849 curproxy->listen->next = listener;
6850 listener = curproxy->listen;
6851
6852 if (!next)
6853 break;
6854
6855 curproxy->listen = next;
6856 }
6857
Willy Tarreaue6b98942007-10-29 01:09:36 +01006858 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006859 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006860 listener = curproxy->listen;
6861 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006862 if (!listener->luid) {
6863 /* listener ID not set, use automatic numbering with first
6864 * spare entry starting with next_luid.
6865 */
6866 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6867 listener->conf.id.key = listener->luid = next_id;
6868 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006869 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006870 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006871
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006872 /* enable separate counters */
6873 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6874 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6875 if (!listener->name) {
6876 sprintf(trash, "sock-%d", listener->luid);
6877 listener->name = strdup(trash);
6878 }
6879 }
6880
Emeric Brun6e159292012-05-18 16:32:13 +02006881#ifdef USE_OPENSSL
David BERARDe566ecb2012-09-04 15:15:13 +02006882#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
6883#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
6884#endif
6885
Emeric Brun6e159292012-05-18 16:32:13 +02006886#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6887#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6888#endif
6889#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6890#define SSL_OP_NO_COMPRESSION 0
6891#endif
6892#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6893#define SSL_MODE_RELEASE_BUFFERS 0
6894#endif
6895 /* Initialize SSL */
6896 if (listener->ssl_cert) {
6897 int ssloptions =
6898 SSL_OP_ALL | /* all known workarounds for bugs */
6899 SSL_OP_NO_SSLv2 |
6900 SSL_OP_NO_COMPRESSION |
6901 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6902 int sslmode =
6903 SSL_MODE_ENABLE_PARTIAL_WRITE |
6904 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6905 SSL_MODE_RELEASE_BUFFERS;
6906
6907 listener->data = &ssl_sock; /* data layer */
6908 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6909 if (!listener->ssl_ctx.ctx) {
6910 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6911 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6912 cfgerr++;
6913 goto skip_ssl;
6914 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006915 if (listener->ssl_ctx.nosslv3)
6916 ssloptions |= SSL_OP_NO_SSLv3;
6917 if (listener->ssl_ctx.notlsv1)
6918 ssloptions |= SSL_OP_NO_TLSv1;
David BERARDe566ecb2012-09-04 15:15:13 +02006919 if (listener->ssl_ctx.prefer_server_ciphers)
6920 ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brun6e159292012-05-18 16:32:13 +02006921 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6922 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6923 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
Emeric Brunfc32aca2012-09-03 12:10:29 +02006924 if (shared_context_init(global.tune.sslcachesize) < 0) {
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006925 Alert("Unable to allocate SSL session cache.\n");
6926 cfgerr++;
6927 goto skip_ssl;
6928 }
6929 shared_context_set_cache(listener->ssl_ctx.ctx);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006930 if (listener->ssl_ctx.ciphers &&
6931 !SSL_CTX_set_cipher_list(listener->ssl_ctx.ctx, listener->ssl_ctx.ciphers)) {
6932 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for listener %d (%s:%d) using cert '%s'.\n",
6933 curproxy->id, listener->ssl_ctx.ciphers, listener->luid,
6934 listener->conf.file, listener->conf.line, listener->ssl_cert);
6935 cfgerr++;
6936 goto skip_ssl;
6937 }
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006938
Emeric Brune1f38db2012-09-03 20:36:47 +02006939 SSL_CTX_set_info_callback(listener->ssl_ctx.ctx, ssl_sock_infocbk);
Emeric Brun6e159292012-05-18 16:32:13 +02006940
6941 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6942 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6943 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6944 cfgerr++;
6945 goto skip_ssl;
6946 }
6947
6948 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6949 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6950 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6951 cfgerr++;
6952 goto skip_ssl;
6953 }
6954 }
6955 skip_ssl:
6956#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006957 if (curproxy->options & PR_O_TCP_NOLING)
6958 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006959 if (!listener->maxconn)
6960 listener->maxconn = curproxy->maxconn;
6961 if (!listener->backlog)
6962 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006963 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006964 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006965 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006966 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006967 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006968
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006969 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6970 listener->options |= LI_O_TCP_RULES;
6971
Willy Tarreaude3041d2010-05-31 10:56:17 +02006972 if (curproxy->mon_mask.s_addr)
6973 listener->options |= LI_O_CHK_MONNET;
6974
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006975 /* smart accept mode is automatic in HTTP mode */
6976 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreaufbac6632012-09-03 22:33:40 +02006977 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_cert) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006978 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6979 listener->options |= LI_O_NOQUICKACK;
6980
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006981 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006982 listener = listener->next;
6983 }
6984
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006985 /* Check multi-process mode compatibility for the current proxy */
6986 if (global.nbproc > 1) {
6987 int nbproc = 0;
6988 if (curproxy->bind_proc) {
6989 int proc;
6990 for (proc = 0; proc < global.nbproc; proc++) {
6991 if (curproxy->bind_proc & (1 << proc)) {
6992 nbproc++;
6993 }
6994 }
6995 } else {
6996 nbproc = global.nbproc;
6997 }
6998 if (curproxy->table.peers.name) {
6999 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7000 curproxy->id);
7001 cfgerr++;
7002 }
7003 if (nbproc > 1) {
7004 if (curproxy->uri_auth) {
7005 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7006 curproxy->id);
7007 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7008 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7009 curproxy->id);
7010 }
7011 }
7012 if (curproxy->appsession_name) {
7013 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7014 curproxy->id);
7015 }
7016 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7017 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7018 curproxy->id);
7019 }
7020 }
7021 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007022
7023 /* create the task associated with the proxy */
7024 curproxy->task = task_new();
7025 if (curproxy->task) {
7026 curproxy->task->context = curproxy;
7027 curproxy->task->process = manage_proxy;
7028 /* no need to queue, it will be done automatically if some
7029 * listener gets limited.
7030 */
7031 curproxy->task->expire = TICK_ETERNITY;
7032 } else {
7033 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7034 curproxy->id);
7035 cfgerr++;
7036 }
7037
Willy Tarreaubaaee002006-06-26 02:48:02 +02007038 curproxy = curproxy->next;
7039 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007040
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007041 /* Check multi-process mode compatibility */
7042 if (global.nbproc > 1) {
7043 if (global.stats_fe) {
7044 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
7045 }
7046 }
7047
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007048 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7049 struct auth_users *curuser;
7050 int g;
7051
7052 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7053 unsigned int group_mask = 0;
7054 char *group = NULL;
7055
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007056 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007057 continue;
7058
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007059 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007060
7061 for (g = 0; g < curuserlist->grpcnt; g++)
7062 if (!strcmp(curuserlist->groups[g], group))
7063 break;
7064
7065 if (g == curuserlist->grpcnt) {
7066 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7067 curuserlist->name, group, curuser->user);
7068 err_code |= ERR_ALERT | ERR_FATAL;
7069 goto out;
7070 }
7071
7072 group_mask |= (1 << g);
7073 }
7074
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007075 free(curuser->u.groups);
7076 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007077 }
7078
7079 for (g = 0; g < curuserlist->grpcnt; g++) {
7080 char *user = NULL;
7081
7082 if (!curuserlist->groupusers[g])
7083 continue;
7084
7085 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7086 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7087 if (!strcmp(curuser->user, user))
7088 break;
7089
7090 if (!curuser) {
7091 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7092 curuserlist->name, user, curuserlist->groups[g]);
7093 err_code |= ERR_ALERT | ERR_FATAL;
7094 goto out;
7095 }
7096
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007097 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007098 }
7099
7100 free(curuserlist->groupusers[g]);
7101 }
7102
7103 free(curuserlist->groupusers);
7104
7105#ifdef DEBUG_AUTH
7106 for (g = 0; g < curuserlist->grpcnt; g++) {
7107 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7108
7109 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007110 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007111 fprintf(stderr, " %s", curuser->user);
7112 }
7113
7114 fprintf(stderr, "\n");
7115 }
7116#endif
7117
Willy Tarreaufbb78422011-06-05 15:38:35 +02007118 }
7119
7120 /* automatically compute fullconn if not set. We must not do it in the
7121 * loop above because cross-references are not yet fully resolved.
7122 */
7123 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7124 /* If <fullconn> is not set, let's set it to 10% of the sum of
7125 * the possible incoming frontend's maxconns.
7126 */
7127 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7128 struct proxy *fe;
7129 int total = 0;
7130
7131 /* sum up the number of maxconns of frontends which
7132 * reference this backend at least once or which are
7133 * the same one ('listen').
7134 */
7135 for (fe = proxy; fe; fe = fe->next) {
7136 struct switching_rule *rule;
7137 struct hdr_exp *exp;
7138 int found = 0;
7139
7140 if (!(fe->cap & PR_CAP_FE))
7141 continue;
7142
7143 if (fe == curproxy) /* we're on a "listen" instance */
7144 found = 1;
7145
7146 if (fe->defbe.be == curproxy) /* "default_backend" */
7147 found = 1;
7148
7149 /* check if a "use_backend" rule matches */
7150 if (!found) {
7151 list_for_each_entry(rule, &fe->switching_rules, list) {
7152 if (rule->be.backend == curproxy) {
7153 found = 1;
7154 break;
7155 }
7156 }
7157 }
7158
7159 /* check if a "reqsetbe" rule matches */
7160 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7161 if (exp->action == ACT_SETBE &&
7162 (struct proxy *)exp->replace == curproxy) {
7163 found = 1;
7164 break;
7165 }
7166 }
7167
7168 /* now we've checked all possible ways to reference a backend
7169 * from a frontend.
7170 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007171 if (!found)
7172 continue;
7173 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007174 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007175 /* we have the sum of the maxconns in <total>. We only
7176 * keep 10% of that sum to set the default fullconn, with
7177 * a hard minimum of 1 (to avoid a divide by zero).
7178 */
7179 curproxy->fullconn = (total + 9) / 10;
7180 if (!curproxy->fullconn)
7181 curproxy->fullconn = 1;
7182 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007183 }
7184
Willy Tarreau056f5682010-06-06 15:51:11 +02007185 /* initialize stick-tables on backend capable proxies. This must not
7186 * be done earlier because the data size may be discovered while parsing
7187 * other proxies.
7188 */
7189 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007190 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007191
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007192 /*
7193 * Recount currently required checks.
7194 */
7195
7196 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7197 int optnum;
7198
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007199 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7200 if (curproxy->options & cfg_opts[optnum].val)
7201 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007202
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007203 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7204 if (curproxy->options2 & cfg_opts2[optnum].val)
7205 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007206 }
7207
Willy Tarreau122541c2011-09-07 21:24:49 +02007208 if (peers) {
7209 struct peers *curpeers = peers, **last;
7210 struct peer *p, *pb;
7211
7212 /* Remove all peers sections which don't have a valid listener.
7213 * This can happen when a peers section is never referenced and
7214 * does not contain a local peer.
7215 */
7216 last = &peers;
7217 while (*last) {
7218 curpeers = *last;
7219 if (curpeers->peers_fe) {
7220 last = &curpeers->next;
7221 continue;
7222 }
7223
7224 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7225 curpeers->id, localpeer);
7226
7227 p = curpeers->remote;
7228 while (p) {
7229 pb = p->next;
7230 free(p->id);
7231 free(p);
7232 p = pb;
7233 }
7234
7235 /* Destroy and unlink this curpeers section.
7236 * Note: curpeers is backed up into *last.
7237 */
7238 free(curpeers->id);
7239 curpeers = curpeers->next;
7240 free(*last);
7241 *last = curpeers;
7242 }
7243 }
7244
Willy Tarreauac1932d2011-10-24 19:14:41 +02007245 if (!global.tune.max_http_hdr)
7246 global.tune.max_http_hdr = MAX_HTTP_HDR;
7247
Willy Tarreau34eb6712011-10-24 18:15:04 +02007248 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007249 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007250 MEM_F_SHARED);
7251
Willy Tarreaubb925012009-07-23 13:36:36 +02007252 if (cfgerr > 0)
7253 err_code |= ERR_ALERT | ERR_FATAL;
7254 out:
7255 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256}
7257
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007258/*
7259 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7260 * parsing sessions.
7261 */
7262void cfg_register_keywords(struct cfg_kw_list *kwl)
7263{
7264 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7265}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007266
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007267/*
7268 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7269 */
7270void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7271{
7272 LIST_DEL(&kwl->list);
7273 LIST_INIT(&kwl->list);
7274}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007275
7276/*
7277 * Local variables:
7278 * c-indent-level: 8
7279 * c-basic-offset: 8
7280 * End:
7281 */