blob: dcc019b940f9049b742b6d783a3ebeec6e3f032d [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 Tarreau81c25d02011-09-07 15:17:21 +0200724 else if (!strcmp(args[0], "maxconnrate")) {
725 if (global.cps_lim != 0) {
726 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT;
728 goto out;
729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735 global.cps_lim = atol(args[1]);
736 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100737 else if (!strcmp(args[0], "maxpipes")) {
738 if (global.maxpipes != 0) {
739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100747 }
748 global.maxpipes = atol(args[1]);
749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 else if (!strcmp(args[0], "ulimit-n")) {
751 if (global.rlimit_nofile != 0) {
752 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 }
756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 }
761 global.rlimit_nofile = atol(args[1]);
762 }
763 else if (!strcmp(args[0], "chroot")) {
764 if (global.chroot != NULL) {
765 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774 global.chroot = strdup(args[1]);
775 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200776 else if (!strcmp(args[0], "description")) {
777 int i, len=0;
778 char *d;
779
780 if (!*args[1]) {
781 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
782 file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786
787 for(i=1; *args[i]; i++)
788 len += strlen(args[i])+1;
789
790 if (global.desc)
791 free(global.desc);
792
793 global.desc = d = (char *)calloc(1, len);
794
795 d += sprintf(d, "%s", args[1]);
796 for(i=2; *args[i]; i++)
797 d += sprintf(d, " %s", args[i]);
798 }
799 else if (!strcmp(args[0], "node")) {
800 int i;
801 char c;
802
803 for (i=0; args[1][i]; i++) {
804 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100805 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
806 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200807 break;
808 }
809
810 if (!i || args[1][i]) {
811 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
812 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
813 file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817
818 if (global.node)
819 free(global.node);
820
821 global.node = strdup(args[1]);
822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 else if (!strcmp(args[0], "pidfile")) {
824 if (global.pidfile != NULL) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT;
827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 }
834 global.pidfile = strdup(args[1]);
835 }
Emeric Bruned760922010-10-22 17:59:25 +0200836 else if (!strcmp(args[0], "unix-bind")) {
837 int cur_arg = 1;
838 while (*(args[cur_arg])) {
839 if (!strcmp(args[cur_arg], "prefix")) {
840 if (global.unix_bind.prefix != NULL) {
841 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
842 err_code |= ERR_ALERT;
843 cur_arg += 2;
844 continue;
845 }
846
847 if (*(args[cur_arg+1]) == 0) {
848 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852 global.unix_bind.prefix = strdup(args[cur_arg+1]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "mode")) {
858
859 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
860 cur_arg += 2;
861 continue;
862 }
863
864 if (!strcmp(args[cur_arg], "uid")) {
865
866 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
867 cur_arg += 2;
868 continue;
869 }
870
871 if (!strcmp(args[cur_arg], "gid")) {
872
873 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
874 cur_arg += 2;
875 continue;
876 }
877
878 if (!strcmp(args[cur_arg], "user")) {
879 struct passwd *user;
880
881 user = getpwnam(args[cur_arg + 1]);
882 if (!user) {
883 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
884 file, linenum, args[0], args[cur_arg + 1 ]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888
889 global.unix_bind.ux.uid = user->pw_uid;
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "group")) {
895 struct group *group;
896
897 group = getgrnam(args[cur_arg + 1]);
898 if (!group) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\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.gid = group->gr_gid;
906 cur_arg += 2;
907 continue;
908 }
909
Willy Tarreaub48f9582011-09-05 01:17:06 +0200910 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200911 file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915 }
William Lallemand0f99e342011-10-12 17:50:54 +0200916 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
917 /* delete previous herited or defined syslog servers */
918 struct logsrv *back;
919 struct logsrv *tmp;
920
921 if (*(args[1]) != 0) {
922 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926
927 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
928 LIST_DEL(&tmp->list);
929 free(tmp);
930 }
931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200933 struct logsrv *logsrv;
934
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 if (*(args[1]) == 0 || *(args[2]) == 0) {
936 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
William Lallemand0f99e342011-10-12 17:50:54 +0200940
941 logsrv = calloc(1, sizeof(struct logsrv));
942
943 logsrv->facility = get_log_facility(args[2]);
944 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200947 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949
William Lallemand0f99e342011-10-12 17:50:54 +0200950 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200952 logsrv->level = get_log_level(args[3]);
953 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200956 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 }
959
William Lallemand0f99e342011-10-12 17:50:54 +0200960 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200961 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200962 logsrv->minlvl = get_log_level(args[4]);
963 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200964 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200967 }
968 }
969
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100971 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100972 if (!sk) {
973 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100974 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100975 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200976 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100977 goto out;
978 }
William Lallemand0f99e342011-10-12 17:50:54 +0200979 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100980 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100981 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100982 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100983 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
984 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200985 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100986 goto out;
987 }
William Lallemand0f99e342011-10-12 17:50:54 +0200988 logsrv->addr = *sk;
989 if (!get_host_port(&logsrv->addr))
990 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992
William Lallemand0f99e342011-10-12 17:50:54 +0200993 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200994 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100995 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
996 char *name;
997 int len;
998
999 if (global.log_send_hostname != NULL) {
1000 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT;
1002 goto out;
1003 }
1004
1005 if (*(args[1]))
1006 name = args[1];
1007 else
1008 name = hostname;
1009
1010 len = strlen(name);
1011
1012 /* We'll add a space after the name to respect the log format */
1013 free(global.log_send_hostname);
1014 global.log_send_hostname = malloc(len + 2);
1015 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1016 }
Kevinm48936af2010-12-22 16:08:21 +00001017 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1018 if (*(args[1]) == 0) {
1019 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 free(global.log_tag);
1024 global.log_tag = strdup(args[1]);
1025 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001026 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1027 if (global.spread_checks != 0) {
1028 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT;
1030 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001031 }
1032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001036 }
1037 global.spread_checks = atol(args[1]);
1038 if (global.spread_checks < 0 || global.spread_checks > 50) {
1039 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 struct cfg_kw_list *kwl;
1045 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001047
1048 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1049 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1050 if (kwl->kw[index].section != CFG_GLOBAL)
1051 continue;
1052 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1053 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001054 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001055 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001056 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001057 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001058 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001061 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001062 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_WARN;
1064 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001065 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001067 }
1068 }
1069 }
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001074
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001076 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078}
1079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001087
1088 defproxy.defsrv.inter = DEF_CHKINTR;
1089 defproxy.defsrv.fastinter = 0;
1090 defproxy.defsrv.downinter = 0;
1091 defproxy.defsrv.rise = DEF_RISETIME;
1092 defproxy.defsrv.fall = DEF_FALLTIME;
1093 defproxy.defsrv.check_port = 0;
1094 defproxy.defsrv.maxqueue = 0;
1095 defproxy.defsrv.minconn = 0;
1096 defproxy.defsrv.maxconn = 0;
1097 defproxy.defsrv.slowstart = 0;
1098 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1099 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1100 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101}
1102
Willy Tarreauade5ec42010-01-28 19:33:49 +01001103
1104static int create_cond_regex_rule(const char *file, int line,
1105 struct proxy *px, int dir, int action, int flags,
1106 const char *cmd, const char *reg, const char *repl,
1107 const char **cond_start)
1108{
1109 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001110 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001132 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1134 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001146 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001164 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001173 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001174 err_code |= ERR_WARN;
1175
Willy Tarreauf4068b62012-05-08 17:37:49 +02001176 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001177 return err_code;
1178 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001179 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001180 free(preg);
1181 return err_code;
1182}
1183
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001185 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001186 * Returns the error code, 0 if OK, or any combination of :
1187 * - ERR_ABORT: must abort ASAP
1188 * - ERR_FATAL: we can continue parsing but not start the service
1189 * - ERR_WARN: a warning has been emitted
1190 * - ERR_ALERT: an alert has been emitted
1191 * Only the two first ones can stop processing, the two others are just
1192 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001194int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1195{
1196 static struct peers *curpeers = NULL;
1197 struct peer *newpeer = NULL;
1198 const char *err;
1199 int err_code = 0;
1200
1201 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1202
1203 err = invalid_char(args[1]);
1204 if (err) {
1205 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1206 file, linenum, *err, args[0], args[1]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 }
1209
1210 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1211 /*
1212 * If there are two proxies with the same name only following
1213 * combinations are allowed:
1214 */
1215 if (strcmp(curpeers->id, args[1]) == 0) {
1216 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1217 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1218 err_code |= ERR_WARN;
1219 }
1220 }
1221
1222 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1224 err_code |= ERR_ALERT | ERR_ABORT;
1225 goto out;
1226 }
1227
1228 curpeers->next = peers;
1229 peers = curpeers;
1230 curpeers->conf.file = file;
1231 curpeers->conf.line = linenum;
1232 curpeers->last_change = now.tv_sec;
1233 curpeers->id = strdup(args[1]);
1234 }
1235 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1236 char *rport, *raddr;
1237 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001238 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001239
1240 if (!*args[2]) {
1241 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 err = invalid_char(args[1]);
1248 if (err) {
1249 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1250 file, linenum, *err, args[1]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254
1255 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1256 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1257 err_code |= ERR_ALERT | ERR_ABORT;
1258 goto out;
1259 }
1260
1261 /* the peers are linked backwards first */
1262 curpeers->count++;
1263 newpeer->next = curpeers->remote;
1264 curpeers->remote = newpeer;
1265 newpeer->peers = curpeers;
1266 newpeer->conf.file = file;
1267 newpeer->conf.line = linenum;
1268
1269 newpeer->last_change = now.tv_sec;
1270 newpeer->id = strdup(args[1]);
1271
1272 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001273 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001274 if (rport) {
1275 *rport++ = 0;
1276 realport = atol(rport);
1277 }
1278 if (!realport) {
1279 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283
Willy Tarreaufab5a432011-03-04 15:31:53 +01001284 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001285 free(raddr);
1286 if (!sk) {
1287 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001292 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001293 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001294 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001295
1296 if (!sk) {
1297 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1298 file, linenum, newpeer->addr.ss_family, args[2]);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001303 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001304
1305 if (strcmp(newpeer->id, localpeer) == 0) {
1306 /* Current is local peer, it define a frontend */
1307 newpeer->local = 1;
1308
1309 if (!curpeers->peers_fe) {
1310 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1312 err_code |= ERR_ALERT | ERR_ABORT;
1313 goto out;
1314 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001315
Willy Tarreau237250c2011-07-29 01:49:03 +02001316 init_new_proxy(curpeers->peers_fe);
1317 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001318
1319 curpeers->peers_fe->last_change = now.tv_sec;
1320 curpeers->peers_fe->id = strdup(args[1]);
1321 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001322 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001323 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1324 curpeers->peers_fe->timeout.connect = 5000;
1325 curpeers->peers_fe->accept = peer_accept;
1326 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001327 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001328 err_code |= ERR_FATAL;
1329 goto out;
1330 }
1331 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1332 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1333 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1334 curpeers->peers_fe->listen->accept = session_accept;
1335 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1336 curpeers->peers_fe->listen->handler = process_session;
1337 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001338 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1339 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001340 }
1341 }
1342 } /* neither "peer" nor "peers" */
1343 else if (*args[0] != 0) {
1344 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348
1349out:
1350 return err_code;
1351}
1352
1353
Willy Tarreau3842f002009-06-14 11:39:52 +02001354int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355{
1356 static struct proxy *curproxy = NULL;
1357 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001358 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001359 int rc;
1360 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001361 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001362 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001363 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001364 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365
Willy Tarreau977b8e42006-12-29 14:19:17 +01001366 if (!strcmp(args[0], "listen"))
1367 rc = PR_CAP_LISTEN;
1368 else if (!strcmp(args[0], "frontend"))
1369 rc = PR_CAP_FE | PR_CAP_RS;
1370 else if (!strcmp(args[0], "backend"))
1371 rc = PR_CAP_BE | PR_CAP_RS;
1372 else if (!strcmp(args[0], "ruleset"))
1373 rc = PR_CAP_RS;
1374 else
1375 rc = PR_CAP_NONE;
1376
1377 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 if (!*args[1]) {
1379 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1380 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_ABORT;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001386 err = invalid_char(args[1]);
1387 if (err) {
1388 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1389 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001391 }
1392
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001393 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1394 /*
1395 * If there are two proxies with the same name only following
1396 * combinations are allowed:
1397 *
1398 * listen backend frontend ruleset
1399 * listen - - - -
1400 * backend - - OK -
1401 * frontend - OK - -
1402 * ruleset - - - -
1403 */
1404
1405 if (!strcmp(curproxy->id, args[1]) &&
1406 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1407 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001408 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1409 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1410 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001411 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001412 }
1413 }
1414
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001417 err_code |= ERR_ALERT | ERR_ABORT;
1418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001420
Willy Tarreau97cb7802010-01-03 20:23:58 +01001421 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 curproxy->next = proxy;
1423 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 curproxy->conf.file = file;
1425 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001426 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001428 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429
1430 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001431 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001432 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001433 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_FATAL;
1435 goto out;
1436 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001437 new = curproxy->listen;
1438 while (new != last) {
1439 new->conf.file = file;
1440 new->conf.line = linenum;
1441 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001442 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 }
1445
1446 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001447 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001448 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001449
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001452 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001453 curproxy->no_options = defproxy.no_options;
1454 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001455 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001456 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001457 curproxy->except_net = defproxy.except_net;
1458 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001459 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001460 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001462 if (defproxy.fwdfor_hdr_len) {
1463 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1464 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1465 }
1466
Willy Tarreaub86db342009-11-30 11:50:16 +01001467 if (defproxy.orgto_hdr_len) {
1468 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1469 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1470 }
1471
Mark Lamourinec2247f02012-01-04 13:02:01 -05001472 if (defproxy.server_id_hdr_len) {
1473 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1474 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1475 }
1476
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477 if (curproxy->cap & PR_CAP_FE) {
1478 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001479 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001480 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481
1482 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001483 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1484 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001485
1486 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 if (curproxy->cap & PR_CAP_BE) {
1490 curproxy->fullconn = defproxy.fullconn;
1491 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001493 if (defproxy.check_req) {
1494 curproxy->check_req = calloc(1, defproxy.check_len);
1495 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1496 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001499 if (defproxy.expect_str) {
1500 curproxy->expect_str = strdup(defproxy.expect_str);
1501 if (defproxy.expect_regex) {
1502 /* note: this regex is known to be valid */
1503 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1504 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1505 }
1506 }
1507
Willy Tarreau67402132012-05-31 20:40:20 +02001508 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (defproxy.cookie_name)
1510 curproxy->cookie_name = strdup(defproxy.cookie_name);
1511 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001512 if (defproxy.cookie_domain)
1513 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001514
Willy Tarreau31936852010-10-06 16:59:56 +02001515 if (defproxy.cookie_maxidle)
1516 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1517
1518 if (defproxy.cookie_maxlife)
1519 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1520
Emeric Brun647caf12009-06-30 17:57:00 +02001521 if (defproxy.rdp_cookie_name)
1522 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1523 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1524
Willy Tarreau01732802007-11-01 22:48:15 +01001525 if (defproxy.url_param_name)
1526 curproxy->url_param_name = strdup(defproxy.url_param_name);
1527 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001528
Benoitaffb4812009-03-25 13:02:10 +01001529 if (defproxy.hh_name)
1530 curproxy->hh_name = strdup(defproxy.hh_name);
1531 curproxy->hh_len = defproxy.hh_len;
1532 curproxy->hh_match_domain = defproxy.hh_match_domain;
1533
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001534 if (defproxy.iface_name)
1535 curproxy->iface_name = strdup(defproxy.iface_name);
1536 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001539 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 if (defproxy.capture_name)
1541 curproxy->capture_name = strdup(defproxy.capture_name);
1542 curproxy->capture_namelen = defproxy.capture_namelen;
1543 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001547 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001548 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001549 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001550 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001551 curproxy->uri_auth = defproxy.uri_auth;
1552 curproxy->mon_net = defproxy.mon_net;
1553 curproxy->mon_mask = defproxy.mon_mask;
1554 if (defproxy.monitor_uri)
1555 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1556 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001557 if (defproxy.defbe.name)
1558 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001559
1560 /* get either a pointer to the logformat string or a copy of it */
1561 curproxy->logformat_string = defproxy.logformat_string;
1562 if (curproxy->logformat_string &&
1563 curproxy->logformat_string != default_http_log_format &&
1564 curproxy->logformat_string != default_tcp_log_format &&
1565 curproxy->logformat_string != clf_http_log_format)
1566 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 }
1568
1569 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001570 curproxy->timeout.connect = defproxy.timeout.connect;
1571 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001572 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001573 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001574 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001575 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001576 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001577 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001578 curproxy->source_addr = defproxy.source_addr;
1579 }
1580
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001582
1583 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001584 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001585 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001586 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001587 LIST_INIT(&node->list);
1588 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1589 }
1590
Willy Tarreau196729e2012-05-31 19:30:26 +02001591 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1592 if (curproxy->uniqueid_format_string)
1593 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001594
1595 /* copy default header unique id */
1596 if (defproxy.header_unique_id)
1597 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001600 curproxy->conf.used_listener_id = EB_ROOT;
1601 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001602
Willy Tarreau93893792009-07-23 13:19:11 +02001603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
1605 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1606 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001607 /* FIXME-20070101: we should do this too at the end of the
1608 * config parsing to free all default values.
1609 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001610 free(defproxy.check_req);
1611 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001612 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001613 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001614 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001615 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001616 free(defproxy.capture_name);
1617 free(defproxy.monitor_uri);
1618 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001619 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001620 free(defproxy.fwdfor_hdr_name);
1621 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001622 free(defproxy.orgto_hdr_name);
1623 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001624 free(defproxy.server_id_hdr_name);
1625 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001626 free(defproxy.expect_str);
1627 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001628
Willy Tarreau39b06652012-06-01 10:58:06 +02001629 if (defproxy.logformat_string != default_http_log_format &&
1630 defproxy.logformat_string != default_tcp_log_format &&
1631 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001632 free(defproxy.logformat_string);
1633
1634 free(defproxy.uniqueid_format_string);
1635
Willy Tarreaua534fea2008-08-03 12:19:50 +02001636 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001637 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001638
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 /* we cannot free uri_auth because it might already be used */
1640 init_default_instance();
1641 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
1645 else if (curproxy == NULL) {
1646 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 }
1650
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651
1652 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001654 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655 int cur_arg;
1656
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 if (curproxy == &defproxy) {
1658 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664
Emeric Bruned760922010-10-22 17:59:25 +02001665 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001666 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001671
1672 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001673
1674 /* NOTE: the following line might create several listeners if there
1675 * are comma-separated IPs or port ranges. So all further processing
1676 * will have to be applied to all listeners created after last_listen.
1677 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001678 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
1681 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001682
Willy Tarreau90a570f2009-10-04 20:54:54 +02001683 new_listen = curproxy->listen;
1684 while (new_listen != last_listen) {
1685 new_listen->conf.file = file;
1686 new_listen->conf.line = linenum;
1687 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001688 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001689 }
1690
Emeric Bruned760922010-10-22 17:59:25 +02001691 /* Set default global rights and owner for unix bind */
1692 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1693 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1694 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001695 cur_arg = 2;
1696 while (*(args[cur_arg])) {
1697 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1698#ifdef SO_BINDTODEVICE
1699 struct listener *l;
1700
Emeric Bruned760922010-10-22 17:59:25 +02001701 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1702 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1703 file, linenum, args[0], args[cur_arg]);
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001708 if (!*args[cur_arg + 1]) {
1709 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713 }
1714
1715 for (l = curproxy->listen; l != last_listen; l = l->next)
1716 l->interface = strdup(args[cur_arg + 1]);
1717
1718 global.last_checks |= LSTCHK_NETADM;
1719
1720 cur_arg += 2;
1721 continue;
1722#else
1723 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001727#endif
1728 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001729 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1730#ifdef TCP_MAXSEG
1731 struct listener *l;
1732 int mss;
1733
Emeric Bruned760922010-10-22 17:59:25 +02001734 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1735 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1736 file, linenum, args[0], args[cur_arg]);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739 }
1740
Willy Tarreaube1b9182009-06-14 18:48:19 +02001741 if (!*args[cur_arg + 1]) {
1742 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001746 }
1747
Willy Tarreau48a7e722010-12-24 15:26:39 +01001748 mss = atoi(args[cur_arg + 1]);
1749 if (!mss || abs(mss) > 65535) {
1750 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001751 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001754 }
1755
1756 for (l = curproxy->listen; l != last_listen; l = l->next)
1757 l->maxseg = mss;
1758
1759 cur_arg += 2;
1760 continue;
1761#else
1762 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1763 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001766#endif
1767 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001768
1769 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1770#ifdef TCP_DEFER_ACCEPT
1771 struct listener *l;
1772
1773 for (l = curproxy->listen; l != last_listen; l = l->next)
1774 l->options |= LI_O_DEF_ACCEPT;
1775
1776 cur_arg ++;
1777 continue;
1778#else
1779 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1780 file, linenum, args[0], args[cur_arg]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783#endif
1784 }
1785
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001786 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001787#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001788 struct listener *l;
1789
Emeric Bruned760922010-10-22 17:59:25 +02001790 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001797 for (l = curproxy->listen; l != last_listen; l = l->next)
1798 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001799
1800 cur_arg ++;
1801 continue;
1802#else
1803 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1804 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001807#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001808 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001809
Emeric Brun6e159292012-05-18 16:32:13 +02001810 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1811#ifdef USE_OPENSSL
1812 struct listener *l;
1813
1814 if (!*args[cur_arg + 1]) {
1815 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1816 file, linenum, args[0]);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 for (l = curproxy->listen; l != last_listen; l = l->next)
1822 l->ssl_cert = strdup(args[cur_arg + 1]);
1823
1824 cur_arg += 2;
1825 continue;
1826#else
1827 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1828 file, linenum, args[0], args[cur_arg]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831#endif
1832 }
1833
Willy Tarreau8a956912010-10-15 14:27:08 +02001834 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1835 struct listener *l;
1836
1837 for (l = curproxy->listen; l != last_listen; l = l->next)
1838 l->options |= LI_O_ACC_PROXY;
1839
1840 cur_arg ++;
1841 continue;
1842 }
1843
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001844 if (!strcmp(args[cur_arg], "name")) {
1845 struct listener *l;
1846
1847 for (l = curproxy->listen; l != last_listen; l = l->next)
1848 l->name = strdup(args[cur_arg + 1]);
1849
1850 cur_arg += 2;
1851 continue;
1852 }
1853
1854 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001855 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001856 struct listener *l;
1857
1858 if (curproxy->listen->next != last_listen) {
1859 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1860 file, linenum, args[cur_arg]);
1861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
1863 }
1864
1865 if (!*args[cur_arg + 1]) {
1866 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1867 file, linenum, args[cur_arg]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871
1872 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001873 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001874
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001875 if (curproxy->listen->luid <= 0) {
1876 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001877 file, linenum);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001882 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1883 if (node) {
1884 l = container_of(node, struct listener, conf.id);
1885 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1886 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1891
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001892 cur_arg += 2;
1893 continue;
1894 }
1895
Emeric Bruned760922010-10-22 17:59:25 +02001896 if (!strcmp(args[cur_arg], "mode")) {
1897
1898 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1899 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1900 file, linenum, args[0], args[cur_arg]);
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904
1905 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1906
1907 cur_arg += 2;
1908 continue;
1909 }
1910
1911 if (!strcmp(args[cur_arg], "uid")) {
1912
1913 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1914 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1915 file, linenum, args[0], args[cur_arg]);
1916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
1918 }
1919
1920 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1921 cur_arg += 2;
1922 continue;
1923 }
1924
1925 if (!strcmp(args[cur_arg], "gid")) {
1926
1927 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1928 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1929 file, linenum, args[0], args[cur_arg]);
1930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
1932 }
1933
1934 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1935 cur_arg += 2;
1936 continue;
1937 }
1938
1939 if (!strcmp(args[cur_arg], "user")) {
1940 struct passwd *user;
1941
1942 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1943 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1944 file, linenum, args[0], args[cur_arg]);
1945 err_code |= ERR_ALERT | ERR_FATAL;
1946 goto out;
1947 }
1948 user = getpwnam(args[cur_arg + 1]);
1949 if (!user) {
1950 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1951 file, linenum, args[0], args[cur_arg + 1 ]);
1952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
1954 }
1955
1956 curproxy->listen->perm.ux.uid = user->pw_uid;
1957 cur_arg += 2;
1958 continue;
1959 }
1960
1961 if (!strcmp(args[cur_arg], "group")) {
1962 struct group *group;
1963
1964 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1965 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1966 file, linenum, args[0], args[cur_arg]);
1967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
1969 }
1970 group = getgrnam(args[cur_arg + 1]);
1971 if (!group) {
1972 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1973 file, linenum, args[0], args[cur_arg + 1 ]);
1974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
1976 }
1977
1978 curproxy->listen->perm.ux.gid = group->gr_gid;
1979 cur_arg += 2;
1980 continue;
1981 }
1982
Willy Tarreaub48f9582011-09-05 01:17:06 +02001983 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 +01001984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001987 }
Willy Tarreau93893792009-07-23 13:19:11 +02001988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 }
1990 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1991 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1992 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1993 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001999
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 /* flush useless bits */
2001 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002004 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002005 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002007
Willy Tarreau1c47f852006-07-09 08:22:27 +02002008 if (!*args[1]) {
2009 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002013 }
2014
Willy Tarreaua534fea2008-08-03 12:19:50 +02002015 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002016 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002017 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002018 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002019 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2020
Willy Tarreau93893792009-07-23 13:19:11 +02002021 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2024 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2025 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2026 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2027 else {
2028 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
2032 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002033 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002034 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002035
2036 if (curproxy == &defproxy) {
2037 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002041 }
2042
2043 if (!*args[1]) {
2044 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2045 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002048 }
2049
2050 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002051 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002052
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002053 if (curproxy->uuid <= 0) {
2054 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002055 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002058 }
2059
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002060 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2061 if (node) {
2062 struct proxy *target = container_of(node, struct proxy, conf.id);
2063 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2064 file, linenum, proxy_type_str(curproxy), curproxy->id,
2065 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
2068 }
2069 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002070 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002071 else if (!strcmp(args[0], "description")) {
2072 int i, len=0;
2073 char *d;
2074
Cyril Bonté99ed3272010-01-24 23:29:44 +01002075 if (curproxy == &defproxy) {
2076 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2077 file, linenum, args[0]);
2078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
2080 }
2081
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002082 if (!*args[1]) {
2083 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2084 file, linenum, args[0]);
2085 return -1;
2086 }
2087
2088 for(i=1; *args[i]; i++)
2089 len += strlen(args[i])+1;
2090
2091 d = (char *)calloc(1, len);
2092 curproxy->desc = d;
2093
2094 d += sprintf(d, "%s", args[1]);
2095 for(i=2; *args[i]; i++)
2096 d += sprintf(d, " %s", args[i]);
2097
2098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2100 curproxy->state = PR_STSTOPPED;
2101 }
2102 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2103 curproxy->state = PR_STNEW;
2104 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002105 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2106 int cur_arg = 1;
2107 unsigned int set = 0;
2108
2109 while (*args[cur_arg]) {
2110 int u;
2111 if (strcmp(args[cur_arg], "all") == 0) {
2112 set = 0;
2113 break;
2114 }
2115 else if (strcmp(args[cur_arg], "odd") == 0) {
2116 set |= 0x55555555;
2117 }
2118 else if (strcmp(args[cur_arg], "even") == 0) {
2119 set |= 0xAAAAAAAA;
2120 }
2121 else {
2122 u = str2uic(args[cur_arg]);
2123 if (u < 1 || u > 32) {
2124 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2125 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002128 }
2129 if (u > global.nbproc) {
2130 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002133 }
2134 set |= 1 << (u - 1);
2135 }
2136 cur_arg++;
2137 }
2138 curproxy->bind_proc = set;
2139 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002140 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002141 if (curproxy == &defproxy) {
2142 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002145 }
2146
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002147 err = invalid_char(args[1]);
2148 if (err) {
2149 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2150 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002151 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002152 }
2153
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002154 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2155 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2156 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002159 }
2160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2162 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002166
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 if (*(args[1]) == 0) {
2168 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2169 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002173
Willy Tarreau67402132012-05-31 20:40:20 +02002174 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002175 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002176 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002177 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 curproxy->cookie_name = strdup(args[1]);
2179 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002180
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 cur_arg = 2;
2182 while (*(args[cur_arg])) {
2183 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002184 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 }
2186 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002187 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188 }
2189 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002190 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 }
2192 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002193 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 }
2195 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002196 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002198 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002199 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002202 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002204 else if (!strcmp(args[cur_arg], "httponly")) {
2205 curproxy->ck_opts |= PR_CK_HTTPONLY;
2206 }
2207 else if (!strcmp(args[cur_arg], "secure")) {
2208 curproxy->ck_opts |= PR_CK_SECURE;
2209 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002210 else if (!strcmp(args[cur_arg], "domain")) {
2211 if (!*args[cur_arg + 1]) {
2212 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2213 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002216 }
2217
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002218 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002219 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002220 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2221 " dots nor does not start with a dot."
2222 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002223 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002224 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002225 }
2226
2227 err = invalid_domainchar(args[cur_arg + 1]);
2228 if (err) {
2229 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2230 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002233 }
2234
Willy Tarreau68a897b2009-12-03 23:28:34 +01002235 if (!curproxy->cookie_domain) {
2236 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2237 } else {
2238 /* one domain was already specified, add another one by
2239 * building the string which will be returned along with
2240 * the cookie.
2241 */
2242 char *new_ptr;
2243 int new_len = strlen(curproxy->cookie_domain) +
2244 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2245 new_ptr = malloc(new_len);
2246 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2247 free(curproxy->cookie_domain);
2248 curproxy->cookie_domain = new_ptr;
2249 }
Willy Tarreau31936852010-10-06 16:59:56 +02002250 cur_arg++;
2251 }
2252 else if (!strcmp(args[cur_arg], "maxidle")) {
2253 unsigned int maxidle;
2254 const char *res;
2255
2256 if (!*args[cur_arg + 1]) {
2257 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2258 file, linenum, args[cur_arg]);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2264 if (res) {
2265 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2266 file, linenum, *res, args[cur_arg]);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270 curproxy->cookie_maxidle = maxidle;
2271 cur_arg++;
2272 }
2273 else if (!strcmp(args[cur_arg], "maxlife")) {
2274 unsigned int maxlife;
2275 const char *res;
2276
2277 if (!*args[cur_arg + 1]) {
2278 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2279 file, linenum, args[cur_arg]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
2284 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2285 if (res) {
2286 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2287 file, linenum, *res, args[cur_arg]);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002292 cur_arg++;
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002295 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 +02002296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_ALERT | ERR_FATAL;
2298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
2300 cur_arg++;
2301 }
Willy Tarreau67402132012-05-31 20:40:20 +02002302 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2304 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 }
2307
Willy Tarreau67402132012-05-31 20:40:20 +02002308 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2310 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002313
Willy Tarreau67402132012-05-31 20:40:20 +02002314 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002315 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2316 file, linenum);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002320 else if (!strcmp(args[0], "persist")) { /* persist */
2321 if (*(args[1]) == 0) {
2322 Alert("parsing [%s:%d] : missing persist method.\n",
2323 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002326 }
2327
2328 if (!strncmp(args[1], "rdp-cookie", 10)) {
2329 curproxy->options2 |= PR_O2_RDPC_PRST;
2330
Emeric Brunb982a3d2010-01-04 15:45:53 +01002331 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002332 const char *beg, *end;
2333
2334 beg = args[1] + 11;
2335 end = strchr(beg, ')');
2336
2337 if (!end || end == beg) {
2338 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2339 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002342 }
2343
2344 free(curproxy->rdp_cookie_name);
2345 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2346 curproxy->rdp_cookie_len = end-beg;
2347 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002348 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002349 free(curproxy->rdp_cookie_name);
2350 curproxy->rdp_cookie_name = strdup("msts");
2351 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2352 }
2353 else { /* syntax */
2354 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2355 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002358 }
2359 }
2360 else {
2361 Alert("parsing [%s:%d] : unknown persist method.\n",
2362 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002365 }
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002368 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002370 if (curproxy == &defproxy) {
2371 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
2374 }
2375
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002380 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 curproxy->appsession_name = strdup(args[1]);
2388 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2389 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002390 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2391 if (err) {
2392 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2393 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002396 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002397 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002398
Willy Tarreau51041c72007-09-09 21:56:53 +02002399 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002404
2405 cur_arg = 6;
2406 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002407 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2408 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002409 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002410 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002411 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002412 } else if (!strcmp(args[cur_arg], "prefix")) {
2413 curproxy->options2 |= PR_O2_AS_PFX;
2414 } else if (!strcmp(args[cur_arg], "mode")) {
2415 if (!*args[cur_arg + 1]) {
2416 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2417 file, linenum, args[0], args[cur_arg]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421
2422 cur_arg++;
2423 if (!strcmp(args[cur_arg], "query-string")) {
2424 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2425 curproxy->options2 |= PR_O2_AS_M_QS;
2426 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2427 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2428 curproxy->options2 |= PR_O2_AS_M_PP;
2429 } else {
2430 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
2433 }
2434 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002435 cur_arg++;
2436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 } /* Url App Session */
2438 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002439 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002443 if (curproxy == &defproxy) {
2444 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 if (*(args[4]) == 0) {
2450 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2451 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002455 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 curproxy->capture_name = strdup(args[2]);
2457 curproxy->capture_namelen = strlen(curproxy->capture_name);
2458 curproxy->capture_len = atol(args[4]);
2459 if (curproxy->capture_len >= CAPTURE_LEN) {
2460 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2461 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 curproxy->capture_len = CAPTURE_LEN - 1;
2464 }
2465 curproxy->to_log |= LW_COOKIE;
2466 }
2467 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2468 struct cap_hdr *hdr;
2469
2470 if (curproxy == &defproxy) {
2471 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 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475
2476 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2477 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2478 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 }
2482
2483 hdr = calloc(sizeof(struct cap_hdr), 1);
2484 hdr->next = curproxy->req_cap;
2485 hdr->name = strdup(args[3]);
2486 hdr->namelen = strlen(args[3]);
2487 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002488 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 hdr->index = curproxy->nb_req_cap++;
2490 curproxy->req_cap = hdr;
2491 curproxy->to_log |= LW_REQHDR;
2492 }
2493 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2494 struct cap_hdr *hdr;
2495
2496 if (curproxy == &defproxy) {
2497 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 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
2501
2502 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2503 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2504 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }
2508 hdr = calloc(sizeof(struct cap_hdr), 1);
2509 hdr->next = curproxy->rsp_cap;
2510 hdr->name = strdup(args[3]);
2511 hdr->namelen = strlen(args[3]);
2512 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002513 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 hdr->index = curproxy->nb_rsp_cap++;
2515 curproxy->rsp_cap = hdr;
2516 curproxy->to_log |= LW_RSPHDR;
2517 }
2518 else {
2519 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002528
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 if (*(args[1]) == 0) {
2530 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2531 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 }
2535 curproxy->conn_retries = atol(args[1]);
2536 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002537 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002538 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002539
2540 if (curproxy == &defproxy) {
2541 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
2544 }
2545
Willy Tarreauff011f22011-01-06 17:51:27 +01002546 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 +01002547 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2548 file, linenum, args[0]);
2549 err_code |= ERR_WARN;
2550 }
2551
Willy Tarreauff011f22011-01-06 17:51:27 +01002552 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002553
Willy Tarreauff011f22011-01-06 17:51:27 +01002554 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002555 err_code |= ERR_ALERT | ERR_ABORT;
2556 goto out;
2557 }
2558
Willy Tarreauff011f22011-01-06 17:51:27 +01002559 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2560 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002561 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002562 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2563 /* set the header name and length into the proxy structure */
2564 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2565 err_code |= ERR_WARN;
2566
2567 if (!*args[1]) {
2568 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2569 file, linenum, args[0]);
2570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
2572 }
2573
2574 /* set the desired header name */
2575 free(curproxy->server_id_hdr_name);
2576 curproxy->server_id_hdr_name = strdup(args[1]);
2577 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2578 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002579 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002580 if (curproxy == &defproxy) {
2581 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002584 }
2585
Willy Tarreauef6494c2010-01-28 17:12:36 +01002586 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002587 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002591 }
2592
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002593 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2594 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2595 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002598 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002599
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002600 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002601 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002602 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002604 struct redirect_rule *rule;
2605 int cur_arg;
2606 int type = REDIRECT_TYPE_NONE;
2607 int code = 302;
2608 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002609 char *cookie = NULL;
2610 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002611 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002612
Cyril Bonté99ed3272010-01-24 23:29:44 +01002613 if (curproxy == &defproxy) {
2614 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
2618
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 cur_arg = 1;
2620 while (*(args[cur_arg])) {
2621 if (!strcmp(args[cur_arg], "location")) {
2622 if (!*args[cur_arg + 1]) {
2623 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2624 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002627 }
2628
2629 type = REDIRECT_TYPE_LOCATION;
2630 cur_arg++;
2631 destination = args[cur_arg];
2632 }
2633 else if (!strcmp(args[cur_arg], "prefix")) {
2634 if (!*args[cur_arg + 1]) {
2635 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2636 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002639 }
2640
2641 type = REDIRECT_TYPE_PREFIX;
2642 cur_arg++;
2643 destination = args[cur_arg];
2644 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002645 else if (!strcmp(args[cur_arg], "set-cookie")) {
2646 if (!*args[cur_arg + 1]) {
2647 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2648 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002651 }
2652
2653 cur_arg++;
2654 cookie = args[cur_arg];
2655 cookie_set = 1;
2656 }
2657 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2658 if (!*args[cur_arg + 1]) {
2659 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2660 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002663 }
2664
2665 cur_arg++;
2666 cookie = args[cur_arg];
2667 cookie_set = 0;
2668 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 else if (!strcmp(args[cur_arg],"code")) {
2670 if (!*args[cur_arg + 1]) {
2671 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2672 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002675 }
2676 cur_arg++;
2677 code = atol(args[cur_arg]);
2678 if (code < 301 || code > 303) {
2679 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2680 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002683 }
2684 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002685 else if (!strcmp(args[cur_arg],"drop-query")) {
2686 flags |= REDIRECT_FLAG_DROP_QS;
2687 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002688 else if (!strcmp(args[cur_arg],"append-slash")) {
2689 flags |= REDIRECT_FLAG_APPEND_SLASH;
2690 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002691 else if (strcmp(args[cur_arg], "if") == 0 ||
2692 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002693 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002694 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002695 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2696 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002700 break;
2701 }
2702 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002703 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 +02002704 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002707 }
2708 cur_arg++;
2709 }
2710
2711 if (type == REDIRECT_TYPE_NONE) {
2712 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002716 }
2717
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002718 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2719 rule->cond = cond;
2720 rule->rdr_str = strdup(destination);
2721 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002722 if (cookie) {
2723 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002724 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002725 */
2726 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002727 if (cookie_set) {
2728 rule->cookie_str = malloc(rule->cookie_len + 10);
2729 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2730 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2731 rule->cookie_len += 9;
2732 } else {
2733 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002734 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002735 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2736 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002737 }
2738 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002739 rule->type = type;
2740 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002741 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002742 LIST_INIT(&rule->list);
2743 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002744 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2745 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002746 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002747 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002748 struct switching_rule *rule;
2749
Willy Tarreaub099aca2008-10-12 17:26:37 +02002750 if (curproxy == &defproxy) {
2751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002754 }
2755
Willy Tarreau55ea7572007-06-17 19:56:27 +02002756 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002758
2759 if (*(args[1]) == 0) {
2760 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002763 }
2764
Willy Tarreauef6494c2010-01-28 17:12:36 +01002765 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002766 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002770 }
2771
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002772 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2773 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2774 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002777 }
2778
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002779 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002780
Willy Tarreau55ea7572007-06-17 19:56:27 +02002781 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2782 rule->cond = cond;
2783 rule->be.name = strdup(args[1]);
2784 LIST_INIT(&rule->list);
2785 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2786 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002787 else if (strcmp(args[0], "use-server") == 0) {
2788 struct server_rule *rule;
2789
2790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795
2796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2797 err_code |= ERR_WARN;
2798
2799 if (*(args[1]) == 0) {
2800 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
2803 }
2804
2805 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2806 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2807 file, linenum, args[0]);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810 }
2811
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002812 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2813 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2814 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
2817 }
2818
2819 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2820
2821 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2822 rule->cond = cond;
2823 rule->srv.name = strdup(args[1]);
2824 LIST_INIT(&rule->list);
2825 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2826 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2827 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002828 else if ((!strcmp(args[0], "force-persist")) ||
2829 (!strcmp(args[0], "ignore-persist"))) {
2830 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002831
2832 if (curproxy == &defproxy) {
2833 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837
2838 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2839 err_code |= ERR_WARN;
2840
Willy Tarreauef6494c2010-01-28 17:12:36 +01002841 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002842 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2843 file, linenum, args[0]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002848 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2849 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2850 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
2854
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002855 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002856
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002857 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002858 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002859 if (!strcmp(args[0], "force-persist")) {
2860 rule->type = PERSIST_TYPE_FORCE;
2861 } else {
2862 rule->type = PERSIST_TYPE_IGNORE;
2863 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002864 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002865 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002866 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 else if (!strcmp(args[0], "stick-table")) {
2868 int myidx = 1;
2869
Emeric Brun32da3c42010-09-23 18:39:19 +02002870 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002871 curproxy->table.type = (unsigned int)-1;
2872 while (*args[myidx]) {
2873 const char *err;
2874
2875 if (strcmp(args[myidx], "size") == 0) {
2876 myidx++;
2877 if (!*(args[myidx])) {
2878 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2879 file, linenum, args[myidx-1]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2884 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2885 file, linenum, *err, args[myidx-1]);
2886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
2888 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002889 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002891 else if (strcmp(args[myidx], "peers") == 0) {
2892 myidx++;
2893 if (!*(args[myidx])) {
2894 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2895 file, linenum, args[myidx-1]);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
2899 curproxy->table.peers.name = strdup(args[myidx++]);
2900 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002901 else if (strcmp(args[myidx], "expire") == 0) {
2902 myidx++;
2903 if (!*(args[myidx])) {
2904 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2905 file, linenum, args[myidx-1]);
2906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
2908 }
2909 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2910 if (err) {
2911 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2912 file, linenum, *err, args[myidx-1]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002917 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002918 }
2919 else if (strcmp(args[myidx], "nopurge") == 0) {
2920 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002921 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002922 }
2923 else if (strcmp(args[myidx], "type") == 0) {
2924 myidx++;
2925 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2926 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2927 file, linenum, args[myidx]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 /* myidx already points to next arg */
2932 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002933 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002934 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002935 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002936
2937 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002938 nw = args[myidx];
2939 while (*nw) {
2940 /* the "store" keyword supports a comma-separated list */
2941 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002942 sa = NULL; /* store arg */
2943 while (*nw && *nw != ',') {
2944 if (*nw == '(') {
2945 *nw = 0;
2946 sa = ++nw;
2947 while (*nw != ')') {
2948 if (!*nw) {
2949 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2950 file, linenum, args[0], cw);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954 nw++;
2955 }
2956 *nw = '\0';
2957 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002958 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002959 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002960 if (*nw)
2961 *nw++ = '\0';
2962 type = stktable_get_data_type(cw);
2963 if (type < 0) {
2964 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2965 file, linenum, args[0], cw);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
Willy Tarreauac782882010-06-20 10:41:54 +02002969
2970 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2971 switch (err) {
2972 case PE_NONE: break;
2973 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002974 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2975 file, linenum, args[0], cw);
2976 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002977 break;
2978
2979 case PE_ARG_MISSING:
2980 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2981 file, linenum, args[0], cw);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984
2985 case PE_ARG_NOT_USED:
2986 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2987 file, linenum, args[0], cw);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990
2991 default:
2992 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2993 file, linenum, args[0], cw);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002996 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002997 }
2998 myidx++;
2999 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003000 else {
3001 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3002 file, linenum, args[myidx]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003005 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003006 }
3007
3008 if (!curproxy->table.size) {
3009 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3010 file, linenum);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (curproxy->table.type == (unsigned int)-1) {
3016 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3017 file, linenum);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021 }
3022 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003023 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003024 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003025 int myidx = 0;
3026 const char *name = NULL;
3027 int flags;
3028
3029 if (curproxy == &defproxy) {
3030 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
3035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3036 err_code |= ERR_WARN;
3037 goto out;
3038 }
3039
3040 myidx++;
3041 if ((strcmp(args[myidx], "store") == 0) ||
3042 (strcmp(args[myidx], "store-request") == 0)) {
3043 myidx++;
3044 flags = STK_IS_STORE;
3045 }
3046 else if (strcmp(args[myidx], "store-response") == 0) {
3047 myidx++;
3048 flags = STK_IS_STORE | STK_ON_RSP;
3049 }
3050 else if (strcmp(args[myidx], "match") == 0) {
3051 myidx++;
3052 flags = STK_IS_MATCH;
3053 }
3054 else if (strcmp(args[myidx], "on") == 0) {
3055 myidx++;
3056 flags = STK_IS_MATCH | STK_IS_STORE;
3057 }
3058 else {
3059 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063
3064 if (*(args[myidx]) == 0) {
3065 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
3069
David du Colombier7af46052012-05-16 14:16:48 +02003070 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003071 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003072 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
3076
3077 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003078 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003079 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3080 file, linenum, args[0], expr->fetch->kw);
3081 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003082 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003083 goto out;
3084 }
3085 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003086 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003087 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3088 file, linenum, args[0], expr->fetch->kw);
3089 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003090 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003091 goto out;
3092 }
3093 }
3094
3095 if (strcmp(args[myidx], "table") == 0) {
3096 myidx++;
3097 name = args[myidx++];
3098 }
3099
Willy Tarreauef6494c2010-01-28 17:12:36 +01003100 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003101 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3102 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3103 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003104 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003105 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003106 goto out;
3107 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003108 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003109 else if (*(args[myidx])) {
3110 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3111 file, linenum, args[0], args[myidx]);
3112 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003113 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003114 goto out;
3115 }
Emeric Brun97679e72010-09-23 17:56:44 +02003116 if (flags & STK_ON_RSP)
3117 err_code |= warnif_cond_requires_req(cond, file, linenum);
3118 else
3119 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003120
Emeric Brunb982a3d2010-01-04 15:45:53 +01003121 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3122 rule->cond = cond;
3123 rule->expr = expr;
3124 rule->flags = flags;
3125 rule->table.name = name ? strdup(name) : NULL;
3126 LIST_INIT(&rule->list);
3127 if (flags & STK_ON_RSP)
3128 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3129 else
3130 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003133 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003135
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3137 curproxy->uri_auth = NULL; /* we must detach from the default config */
3138
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003139 if (!*args[1]) {
3140 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003141 } else if (!strcmp(args[1], "admin")) {
3142 struct stats_admin_rule *rule;
3143
3144 if (curproxy == &defproxy) {
3145 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
3150 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
3154 }
3155
3156 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3157 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3158 file, linenum, args[0], args[1]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
3161 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003162 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3163 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3164 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168
3169 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3170
3171 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3172 rule->cond = cond;
3173 LIST_INIT(&rule->list);
3174 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 } else if (!strcmp(args[1], "uri")) {
3176 if (*(args[2]) == 0) {
3177 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3181 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_ABORT;
3183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 } else if (!strcmp(args[1], "realm")) {
3186 if (*(args[2]) == 0) {
3187 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_ABORT;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003195 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003196 unsigned interval;
3197
3198 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3199 if (err) {
3200 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3201 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003204 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003208 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003209 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003210 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003211
3212 if (curproxy == &defproxy) {
3213 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
3216 }
3217
3218 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3219 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3220 err_code |= ERR_ALERT | ERR_ABORT;
3221 goto out;
3222 }
3223
Willy Tarreauff011f22011-01-06 17:51:27 +01003224 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3225 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003226 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3227 file, linenum, args[0]);
3228 err_code |= ERR_WARN;
3229 }
3230
Willy Tarreauff011f22011-01-06 17:51:27 +01003231 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003232
Willy Tarreauff011f22011-01-06 17:51:27 +01003233 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003234 err_code |= ERR_ALERT | ERR_ABORT;
3235 goto out;
3236 }
3237
Willy Tarreauff011f22011-01-06 17:51:27 +01003238 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3239 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003240
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 } else if (!strcmp(args[1], "auth")) {
3242 if (*(args[2]) == 0) {
3243 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3247 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 }
3251 } else if (!strcmp(args[1], "scope")) {
3252 if (*(args[2]) == 0) {
3253 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3257 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_ABORT;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261 } else if (!strcmp(args[1], "enable")) {
3262 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003267 } else if (!strcmp(args[1], "hide-version")) {
3268 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_ABORT;
3271 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003272 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003273 } else if (!strcmp(args[1], "show-legends")) {
3274 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3275 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3276 err_code |= ERR_ALERT | ERR_ABORT;
3277 goto out;
3278 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003279 } else if (!strcmp(args[1], "show-node")) {
3280
3281 if (*args[2]) {
3282 int i;
3283 char c;
3284
3285 for (i=0; args[2][i]; i++) {
3286 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003287 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3288 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003289 break;
3290 }
3291
3292 if (!i || args[2][i]) {
3293 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3294 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3295 file, linenum, args[0], args[1]);
3296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
3298 }
3299 }
3300
3301 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3302 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3303 err_code |= ERR_ALERT | ERR_ABORT;
3304 goto out;
3305 }
3306 } else if (!strcmp(args[1], "show-desc")) {
3307 char *desc = NULL;
3308
3309 if (*args[2]) {
3310 int i, len=0;
3311 char *d;
3312
3313 for(i=2; *args[i]; i++)
3314 len += strlen(args[i])+1;
3315
3316 desc = d = (char *)calloc(1, len);
3317
3318 d += sprintf(d, "%s", args[2]);
3319 for(i=3; *args[i]; i++)
3320 d += sprintf(d, " %s", args[i]);
3321 }
3322
3323 if (!*args[2] && !global.desc)
3324 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3325 file, linenum, args[1]);
3326 else {
3327 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3328 free(desc);
3329 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3330 err_code |= ERR_ALERT | ERR_ABORT;
3331 goto out;
3332 }
3333 free(desc);
3334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003336stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003337 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 +01003338 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
3342 }
3343 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003344 int optnum;
3345
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003346 if (*(args[1]) == '\0') {
3347 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003352
3353 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3354 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003355 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3356 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3357 file, linenum, cfg_opts[optnum].name);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3362 err_code |= ERR_WARN;
3363 goto out;
3364 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003365
Willy Tarreau3842f002009-06-14 11:39:52 +02003366 curproxy->no_options &= ~cfg_opts[optnum].val;
3367 curproxy->options &= ~cfg_opts[optnum].val;
3368
3369 switch (kwm) {
3370 case KWM_STD:
3371 curproxy->options |= cfg_opts[optnum].val;
3372 break;
3373 case KWM_NO:
3374 curproxy->no_options |= cfg_opts[optnum].val;
3375 break;
3376 case KWM_DEF: /* already cleared */
3377 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003378 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003379
Willy Tarreau93893792009-07-23 13:19:11 +02003380 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003381 }
3382 }
3383
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003384 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3385 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003386 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3387 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3388 file, linenum, cfg_opts2[optnum].name);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
Willy Tarreau93893792009-07-23 13:19:11 +02003392 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3393 err_code |= ERR_WARN;
3394 goto out;
3395 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003396
Willy Tarreau3842f002009-06-14 11:39:52 +02003397 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3398 curproxy->options2 &= ~cfg_opts2[optnum].val;
3399
3400 switch (kwm) {
3401 case KWM_STD:
3402 curproxy->options2 |= cfg_opts2[optnum].val;
3403 break;
3404 case KWM_NO:
3405 curproxy->no_options2 |= cfg_opts2[optnum].val;
3406 break;
3407 case KWM_DEF: /* already cleared */
3408 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003409 }
Willy Tarreau93893792009-07-23 13:19:11 +02003410 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003411 }
3412 }
3413
Willy Tarreau3842f002009-06-14 11:39:52 +02003414 if (kwm != KWM_STD) {
3415 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003416 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003419 }
3420
Emeric Brun3a058f32009-06-30 18:26:00 +02003421 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003422 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003424 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003425 if (*(args[2]) != '\0') {
3426 if (!strcmp(args[2], "clf")) {
3427 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003428 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003429 } else {
3430 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003431 err_code |= ERR_ALERT | ERR_FATAL;
3432 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003433 }
3434 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003435 if (curproxy->logformat_string != default_http_log_format &&
3436 curproxy->logformat_string != default_tcp_log_format &&
3437 curproxy->logformat_string != clf_http_log_format)
3438 free(curproxy->logformat_string);
3439 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003440 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003441 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003443 if (curproxy->logformat_string != default_http_log_format &&
3444 curproxy->logformat_string != default_tcp_log_format &&
3445 curproxy->logformat_string != clf_http_log_format)
3446 free(curproxy->logformat_string);
3447 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 else if (!strcmp(args[1], "tcpka")) {
3450 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003451 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003452 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003453
3454 if (curproxy->cap & PR_CAP_FE)
3455 curproxy->options |= PR_O_TCP_CLI_KA;
3456 if (curproxy->cap & PR_CAP_BE)
3457 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 }
3459 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003460 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003461 err_code |= ERR_WARN;
3462
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003464 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003465 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003466 curproxy->options2 &= ~PR_O2_CHK_ANY;
3467 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 if (!*args[2]) { /* no argument */
3469 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3470 curproxy->check_len = strlen(DEF_CHECK_REQ);
3471 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003472 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 curproxy->check_req = (char *)malloc(reqlen);
3474 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003475 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003477 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 if (*args[4])
3479 reqlen += strlen(args[4]);
3480 else
3481 reqlen += strlen("HTTP/1.0");
3482
3483 curproxy->check_req = (char *)malloc(reqlen);
3484 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003485 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003487 }
3488 else if (!strcmp(args[1], "ssl-hello-chk")) {
3489 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003490 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003492
Willy Tarreaua534fea2008-08-03 12:19:50 +02003493 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003494 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003495 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003496 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 }
Willy Tarreau23677902007-05-08 23:50:35 +02003498 else if (!strcmp(args[1], "smtpchk")) {
3499 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003500 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003501 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003502 curproxy->options2 &= ~PR_O2_CHK_ANY;
3503 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003504
3505 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3506 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3507 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3508 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3509 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3510 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3511 curproxy->check_req = (char *)malloc(reqlen);
3512 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3513 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3514 } else {
3515 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3516 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3517 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3518 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3519 }
3520 }
3521 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003522 else if (!strcmp(args[1], "pgsql-check")) {
3523 /* use PostgreSQL request to check servers' health */
3524 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3525 err_code |= ERR_WARN;
3526
3527 free(curproxy->check_req);
3528 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003529 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003530 curproxy->options2 |= PR_O2_PGSQL_CHK;
3531
3532 if (*(args[2])) {
3533 int cur_arg = 2;
3534
3535 while (*(args[cur_arg])) {
3536 if (strcmp(args[cur_arg], "user") == 0) {
3537 char * packet;
3538 uint32_t packet_len;
3539 uint32_t pv;
3540
3541 /* suboption header - needs additional argument for it */
3542 if (*(args[cur_arg+1]) == 0) {
3543 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3544 file, linenum, args[0], args[1], args[cur_arg]);
3545 err_code |= ERR_ALERT | ERR_FATAL;
3546 goto out;
3547 }
3548
3549 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3550 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3551 pv = htonl(0x30000); /* protocol version 3.0 */
3552
3553 packet = (char*) calloc(1, packet_len);
3554
3555 memcpy(packet + 4, &pv, 4);
3556
3557 /* copy "user" */
3558 memcpy(packet + 8, "user", 4);
3559
3560 /* copy username */
3561 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3562
3563 free(curproxy->check_req);
3564 curproxy->check_req = packet;
3565 curproxy->check_len = packet_len;
3566
3567 packet_len = htonl(packet_len);
3568 memcpy(packet, &packet_len, 4);
3569 cur_arg += 2;
3570 } else {
3571 /* unknown suboption - catchall */
3572 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3573 file, linenum, args[0], args[1]);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
3577 } /* end while loop */
3578 }
3579 }
3580
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003581 else if (!strcmp(args[1], "redis-check")) {
3582 /* use REDIS PING request to check servers' health */
3583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3584 err_code |= ERR_WARN;
3585
3586 free(curproxy->check_req);
3587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003588 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003589 curproxy->options2 |= PR_O2_REDIS_CHK;
3590
3591 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3592 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3593 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3594 }
3595
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003596 else if (!strcmp(args[1], "mysql-check")) {
3597 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003598 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3599 err_code |= ERR_WARN;
3600
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003601 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003602 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003603 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003604 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003605
3606 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3607 * const char mysql40_client_auth_pkt[] = {
3608 * "\x0e\x00\x00" // packet length
3609 * "\x01" // packet number
3610 * "\x00\x00" // client capabilities
3611 * "\x00\x00\x01" // max packet
3612 * "haproxy\x00" // username (null terminated string)
3613 * "\x00" // filler (always 0x00)
3614 * "\x01\x00\x00" // packet length
3615 * "\x00" // packet number
3616 * "\x01" // COM_QUIT command
3617 * };
3618 */
3619
3620 if (*(args[2])) {
3621 int cur_arg = 2;
3622
3623 while (*(args[cur_arg])) {
3624 if (strcmp(args[cur_arg], "user") == 0) {
3625 char *mysqluser;
3626 int packetlen, reqlen, userlen;
3627
3628 /* suboption header - needs additional argument for it */
3629 if (*(args[cur_arg+1]) == 0) {
3630 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3631 file, linenum, args[0], args[1], args[cur_arg]);
3632 err_code |= ERR_ALERT | ERR_FATAL;
3633 goto out;
3634 }
3635 mysqluser = args[cur_arg + 1];
3636 userlen = strlen(mysqluser);
3637 packetlen = userlen + 7;
3638 reqlen = packetlen + 9;
3639
3640 free(curproxy->check_req);
3641 curproxy->check_req = (char *)calloc(1, reqlen);
3642 curproxy->check_len = reqlen;
3643
3644 snprintf(curproxy->check_req, 4, "%c%c%c",
3645 ((unsigned char) packetlen & 0xff),
3646 ((unsigned char) (packetlen >> 8) & 0xff),
3647 ((unsigned char) (packetlen >> 16) & 0xff));
3648
3649 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003650 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003651 curproxy->check_req[8] = 1;
3652 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3653 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3654 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3655 cur_arg += 2;
3656 } else {
3657 /* unknown suboption - catchall */
3658 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3659 file, linenum, args[0], args[1]);
3660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
3662 }
3663 } /* end while loop */
3664 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003665 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003666 else if (!strcmp(args[1], "ldap-check")) {
3667 /* use LDAP request to check servers' health */
3668 free(curproxy->check_req);
3669 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003670 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003671 curproxy->options2 |= PR_O2_LDAP_CHK;
3672
3673 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3674 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3675 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3676 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003677 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003678 int cur_arg;
3679
3680 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3681 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003682 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003683
Willy Tarreau87cf5142011-08-19 22:57:24 +02003684 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003685
3686 free(curproxy->fwdfor_hdr_name);
3687 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3688 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3689
3690 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3691 cur_arg = 2;
3692 while (*(args[cur_arg])) {
3693 if (!strcmp(args[cur_arg], "except")) {
3694 /* suboption except - needs additional argument for it */
3695 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3696 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3697 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003700 }
3701 /* flush useless bits */
3702 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003703 cur_arg += 2;
3704 } else if (!strcmp(args[cur_arg], "header")) {
3705 /* suboption header - needs additional argument for it */
3706 if (*(args[cur_arg+1]) == 0) {
3707 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3708 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003711 }
3712 free(curproxy->fwdfor_hdr_name);
3713 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3714 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3715 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003716 } else if (!strcmp(args[cur_arg], "if-none")) {
3717 curproxy->options &= ~PR_O_FF_ALWAYS;
3718 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003719 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003720 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003721 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003722 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003725 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003726 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003727 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003728 else if (!strcmp(args[1], "originalto")) {
3729 int cur_arg;
3730
3731 /* insert x-original-to field, but not for the IP address listed as an except.
3732 * set default options (ie: bitfield, header name, etc)
3733 */
3734
3735 curproxy->options |= PR_O_ORGTO;
3736
3737 free(curproxy->orgto_hdr_name);
3738 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3739 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3740
Willy Tarreau87cf5142011-08-19 22:57:24 +02003741 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003742 cur_arg = 2;
3743 while (*(args[cur_arg])) {
3744 if (!strcmp(args[cur_arg], "except")) {
3745 /* suboption except - needs additional argument for it */
3746 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3747 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3748 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003751 }
3752 /* flush useless bits */
3753 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3754 cur_arg += 2;
3755 } else if (!strcmp(args[cur_arg], "header")) {
3756 /* suboption header - needs additional argument for it */
3757 if (*(args[cur_arg+1]) == 0) {
3758 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3759 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003762 }
3763 free(curproxy->orgto_hdr_name);
3764 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3765 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3766 cur_arg += 2;
3767 } else {
3768 /* unknown suboption - catchall */
3769 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3770 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003773 }
3774 } /* end while loop */
3775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 else {
3777 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 }
Willy Tarreau93893792009-07-23 13:19:11 +02003781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003783 else if (!strcmp(args[0], "default_backend")) {
3784 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003786
3787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003791 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003792 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003793 curproxy->defbe.name = strdup(args[1]);
3794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003799 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 /* enable reconnections to dispatch */
3803 curproxy->options |= PR_O_REDISP;
3804 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003805 else if (!strcmp(args[0], "http-check")) {
3806 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003808
3809 if (strcmp(args[1], "disable-on-404") == 0) {
3810 /* enable a graceful server shutdown on an HTTP 404 response */
3811 curproxy->options |= PR_O_DISABLE404;
3812 }
Willy Tarreauef781042010-01-27 11:53:01 +01003813 else if (strcmp(args[1], "send-state") == 0) {
3814 /* enable emission of the apparent state of a server in HTTP checks */
3815 curproxy->options2 |= PR_O2_CHK_SNDST;
3816 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003817 else if (strcmp(args[1], "expect") == 0) {
3818 const char *ptr_arg;
3819 int cur_arg;
3820
3821 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3822 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
3825 }
3826
3827 cur_arg = 2;
3828 /* consider exclamation marks, sole or at the beginning of a word */
3829 while (*(ptr_arg = args[cur_arg])) {
3830 while (*ptr_arg == '!') {
3831 curproxy->options2 ^= PR_O2_EXP_INV;
3832 ptr_arg++;
3833 }
3834 if (*ptr_arg)
3835 break;
3836 cur_arg++;
3837 }
3838 /* now ptr_arg points to the beginning of a word past any possible
3839 * exclamation mark, and cur_arg is the argument which holds this word.
3840 */
3841 if (strcmp(ptr_arg, "status") == 0) {
3842 if (!*(args[cur_arg + 1])) {
3843 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3844 file, linenum, args[0], args[1], ptr_arg);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003849 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003850 curproxy->expect_str = strdup(args[cur_arg + 1]);
3851 }
3852 else if (strcmp(ptr_arg, "string") == 0) {
3853 if (!*(args[cur_arg + 1])) {
3854 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3855 file, linenum, args[0], args[1], ptr_arg);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003860 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003861 curproxy->expect_str = strdup(args[cur_arg + 1]);
3862 }
3863 else if (strcmp(ptr_arg, "rstatus") == 0) {
3864 if (!*(args[cur_arg + 1])) {
3865 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3866 file, linenum, args[0], args[1], ptr_arg);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003871 free(curproxy->expect_str);
3872 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3873 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003874 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3875 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3876 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3877 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
3880 }
3881 }
3882 else if (strcmp(ptr_arg, "rstring") == 0) {
3883 if (!*(args[cur_arg + 1])) {
3884 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3885 file, linenum, args[0], args[1], ptr_arg);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003890 free(curproxy->expect_str);
3891 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3892 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003893 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3894 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3895 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3896 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900 }
3901 else {
3902 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3903 file, linenum, args[0], args[1], ptr_arg);
3904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
3906 }
3907 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003908 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003909 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 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003912 }
3913 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003914 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003915 if (curproxy == &defproxy) {
3916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003919 }
3920
Willy Tarreaub80c2302007-11-30 20:51:32 +01003921 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003923
3924 if (strcmp(args[1], "fail") == 0) {
3925 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003926 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003927 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3928 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003931 }
3932
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003933 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3934 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3935 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003938 }
3939 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3940 }
3941 else {
3942 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003945 }
3946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947#ifdef TPROXY
3948 else if (!strcmp(args[0], "transparent")) {
3949 /* enable transparent proxy connections */
3950 curproxy->options |= PR_O_TRANSP;
3951 }
3952#endif
3953 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003954 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003956
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 if (*(args[1]) == 0) {
3958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
3962 curproxy->maxconn = atol(args[1]);
3963 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003964 else if (!strcmp(args[0], "backlog")) { /* backlog */
3965 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003967
3968 if (*(args[1]) == 0) {
3969 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003972 }
3973 curproxy->backlog = atol(args[1]);
3974 }
Willy Tarreau86034312006-12-29 00:10:33 +01003975 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003976 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003978
Willy Tarreau86034312006-12-29 00:10:33 +01003979 if (*(args[1]) == 0) {
3980 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003983 }
3984 curproxy->fullconn = atol(args[1]);
3985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3987 if (*(args[1]) == 0) {
3988 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003992 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3993 if (err) {
3994 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3995 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003998 }
3999 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 }
4001 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004002 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 if (curproxy == &defproxy) {
4004 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004008 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004010
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 if (strchr(args[1], ':') == NULL) {
4012 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004016 sk = str2sa(args[1]);
4017 if (!sk) {
4018 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004023 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 }
4025 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004028
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004029 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4030 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004035 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4037 err_code |= ERR_WARN;
4038
4039 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4040 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4041 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4042 }
4043 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4044 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4045 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4046 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004047 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4048 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4049 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4050 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004051 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004052 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
4055 }
4056 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004059 char *rport, *raddr;
4060 short realport = 0;
4061 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004068 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004069 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070
4071 if (!*args[2]) {
4072 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004077
4078 err = invalid_char(args[1]);
4079 if (err) {
4080 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4081 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004084 }
4085
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004086 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004087 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004088
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004089 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4091 err_code |= ERR_ALERT | ERR_ABORT;
4092 goto out;
4093 }
4094
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004095 /* the servers are linked backwards first */
4096 newsrv->next = curproxy->srv;
4097 curproxy->srv = newsrv;
4098 newsrv->proxy = curproxy;
4099 newsrv->conf.file = file;
4100 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101
Simon Hormanaf514952011-06-21 14:34:57 +09004102 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 LIST_INIT(&newsrv->pendconns);
4104 do_check = 0;
4105 newsrv->state = SRV_RUNNING; /* early server setup */
4106 newsrv->last_change = now.tv_sec;
4107 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004110 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004111 * - IP: => port=+0, relative
4112 * - IP:N => port=N, absolute
4113 * - IP:+N => port=+N, relative
4114 * - IP:-N => port=-N, relative
4115 */
4116 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004117 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 if (rport) {
4119 *rport++ = 0;
4120 realport = atol(rport);
4121 if (!isdigit((unsigned char)*rport))
4122 newsrv->state |= SRV_MAPPORTS;
4123 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004125
Willy Tarreaufab5a432011-03-04 15:31:53 +01004126 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004127 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004128 if (!sk) {
4129 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004134 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004135 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004136
4137 if (!sk) {
4138 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4139 file, linenum, newsrv->addr.ss_family, args[2]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004143 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004144
4145 newsrv->check_port = curproxy->defsrv.check_port;
4146 newsrv->inter = curproxy->defsrv.inter;
4147 newsrv->fastinter = curproxy->defsrv.fastinter;
4148 newsrv->downinter = curproxy->defsrv.downinter;
4149 newsrv->rise = curproxy->defsrv.rise;
4150 newsrv->fall = curproxy->defsrv.fall;
4151 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4152 newsrv->minconn = curproxy->defsrv.minconn;
4153 newsrv->maxconn = curproxy->defsrv.maxconn;
4154 newsrv->slowstart = curproxy->defsrv.slowstart;
4155 newsrv->onerror = curproxy->defsrv.onerror;
4156 newsrv->consecutive_errors_limit
4157 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004158#ifdef OPENSSL
4159 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4160#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004161 newsrv->uweight = newsrv->iweight
4162 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004164 newsrv->curfd = -1; /* no health-check in progress */
4165 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004167 cur_arg = 3;
4168 } else {
4169 newsrv = &curproxy->defsrv;
4170 cur_arg = 1;
4171 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004172
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004174 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004175 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004176
4177 if (!*args[cur_arg + 1]) {
4178 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4179 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004182 }
4183
4184 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004185 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004186
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004187 if (newsrv->puid <= 0) {
4188 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004189 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004192 }
4193
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004194 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4195 if (node) {
4196 struct server *target = container_of(node, struct server, conf.id);
4197 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4198 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
4201 }
4202 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004203 cur_arg += 2;
4204 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004205 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 newsrv->cookie = strdup(args[cur_arg + 1]);
4207 newsrv->cklen = strlen(args[cur_arg + 1]);
4208 cur_arg += 2;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004211 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4212 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4213 cur_arg += 2;
4214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004216 if (!*args[cur_arg + 1]) {
4217 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4218 file, linenum, args[cur_arg]);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
4222
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004224 if (newsrv->rise <= 0) {
4225 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4226 file, linenum, args[cur_arg]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
Willy Tarreau96839092010-03-29 10:02:24 +02004231 if (newsrv->health)
4232 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 cur_arg += 2;
4234 }
4235 else if (!strcmp(args[cur_arg], "fall")) {
4236 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004237
4238 if (!*args[cur_arg + 1]) {
4239 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4240 file, linenum, args[cur_arg]);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243 }
4244
4245 if (newsrv->fall <= 0) {
4246 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4247 file, linenum, args[cur_arg]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 cur_arg += 2;
4253 }
4254 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004255 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4256 if (err) {
4257 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4258 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004261 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004262 if (val <= 0) {
4263 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4264 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004267 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004268 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 cur_arg += 2;
4270 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004271 else if (!strcmp(args[cur_arg], "fastinter")) {
4272 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4273 if (err) {
4274 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4275 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004278 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004279 if (val <= 0) {
4280 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4281 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004284 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004285 newsrv->fastinter = val;
4286 cur_arg += 2;
4287 }
4288 else if (!strcmp(args[cur_arg], "downinter")) {
4289 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4290 if (err) {
4291 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4292 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004295 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004296 if (val <= 0) {
4297 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4298 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004301 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004302 newsrv->downinter = val;
4303 cur_arg += 2;
4304 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004305 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004306 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004307 if (!sk) {
4308 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004313 cur_arg += 2;
4314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 else if (!strcmp(args[cur_arg], "port")) {
4316 newsrv->check_port = atol(args[cur_arg + 1]);
4317 cur_arg += 2;
4318 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004319 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 newsrv->state |= SRV_BACKUP;
4321 cur_arg ++;
4322 }
Simon Hormanfa461682011-06-25 09:39:49 +09004323 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4324 newsrv->state |= SRV_NON_STICK;
4325 cur_arg ++;
4326 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004327 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4328 newsrv->state |= SRV_SEND_PROXY;
4329 cur_arg ++;
4330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 else if (!strcmp(args[cur_arg], "weight")) {
4332 int w;
4333 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004334 if (w < 0 || w > 256) {
4335 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004340 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 cur_arg += 2;
4342 }
4343 else if (!strcmp(args[cur_arg], "minconn")) {
4344 newsrv->minconn = atol(args[cur_arg + 1]);
4345 cur_arg += 2;
4346 }
4347 else if (!strcmp(args[cur_arg], "maxconn")) {
4348 newsrv->maxconn = atol(args[cur_arg + 1]);
4349 cur_arg += 2;
4350 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004351 else if (!strcmp(args[cur_arg], "maxqueue")) {
4352 newsrv->maxqueue = atol(args[cur_arg + 1]);
4353 cur_arg += 2;
4354 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004355 else if (!strcmp(args[cur_arg], "slowstart")) {
4356 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004357 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004358 if (err) {
4359 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4360 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004363 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004364 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004365 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4366 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004369 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004370 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004371 cur_arg += 2;
4372 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004374
4375 if (!*args[cur_arg + 1]) {
4376 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004380 }
4381
4382 newsrv->trackit = strdup(args[cur_arg + 1]);
4383
4384 cur_arg += 2;
4385 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004386 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 global.maxsock++;
4388 do_check = 1;
4389 cur_arg += 1;
4390 }
Willy Tarreau96839092010-03-29 10:02:24 +02004391 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4392 newsrv->state |= SRV_MAINTAIN;
4393 newsrv->state &= ~SRV_RUNNING;
4394 newsrv->health = 0;
4395 cur_arg += 1;
4396 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004397 else if (!strcmp(args[cur_arg], "ssl")) {
4398#ifdef USE_OPENSSL
4399 newsrv->use_ssl = 1;
4400 cur_arg += 1;
4401#else /* USE_OPENSSL */
4402 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4403 file, linenum, args[cur_arg]);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406#endif /* USE_OPENSSL */
4407 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004408 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004409 if (!strcmp(args[cur_arg + 1], "none"))
4410 newsrv->observe = HANA_OBS_NONE;
4411 else if (!strcmp(args[cur_arg + 1], "layer4"))
4412 newsrv->observe = HANA_OBS_LAYER4;
4413 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4414 if (curproxy->mode != PR_MODE_HTTP) {
4415 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4416 file, linenum, args[cur_arg + 1]);
4417 err_code |= ERR_ALERT;
4418 }
4419 newsrv->observe = HANA_OBS_LAYER7;
4420 }
4421 else {
4422 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004423 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004424 file, linenum, args[cur_arg], args[cur_arg + 1]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428
4429 cur_arg += 2;
4430 }
4431 else if (!strcmp(args[cur_arg], "on-error")) {
4432 if (!strcmp(args[cur_arg + 1], "fastinter"))
4433 newsrv->onerror = HANA_ONERR_FASTINTER;
4434 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4435 newsrv->onerror = HANA_ONERR_FAILCHK;
4436 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4437 newsrv->onerror = HANA_ONERR_SUDDTH;
4438 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4439 newsrv->onerror = HANA_ONERR_MARKDWN;
4440 else {
4441 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004442 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004443 file, linenum, args[cur_arg], args[cur_arg + 1]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 }
4447
4448 cur_arg += 2;
4449 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004450 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4451 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4452 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4453 else {
4454 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4455 file, linenum, args[cur_arg], args[cur_arg + 1]);
4456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
4458 }
4459
4460 cur_arg += 2;
4461 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004462 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4463 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4464 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4465 else {
4466 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4467 file, linenum, args[cur_arg], args[cur_arg + 1]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 }
4471
4472 cur_arg += 2;
4473 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004474 else if (!strcmp(args[cur_arg], "error-limit")) {
4475 if (!*args[cur_arg + 1]) {
4476 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4477 file, linenum, args[cur_arg]);
4478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
4480 }
4481
4482 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4483
4484 if (newsrv->consecutive_errors_limit <= 0) {
4485 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4486 file, linenum, args[cur_arg]);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004490 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004491 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004492 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004493 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004494 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004495
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004497#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004498 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004499 file, linenum, "source", "usesrc");
4500#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004501 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004503#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
4507 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004508 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4509 if (!sk) {
4510 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
4514 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004515
4516 if (port_low != port_high) {
4517 int i;
4518 if (port_low <= 0 || port_low > 65535 ||
4519 port_high <= 0 || port_high > 65535 ||
4520 port_low > port_high) {
4521 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4522 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004523 err_code |= ERR_ALERT | ERR_FATAL;
4524 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004525 }
4526 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4527 for (i = 0; i < newsrv->sport_range->size; i++)
4528 newsrv->sport_range->ports[i] = port_low + i;
4529 }
4530
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004532 while (*(args[cur_arg])) {
4533 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004534#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4535#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004536 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4537 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4538 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004541 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004542#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004543 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004544 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004545 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004548 }
4549 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004550 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004551 newsrv->state |= SRV_TPROXY_CLI;
4552 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004553 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004554 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004555 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4556 char *name, *end;
4557
4558 name = args[cur_arg+1] + 7;
4559 while (isspace(*name))
4560 name++;
4561
4562 end = name;
4563 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4564 end++;
4565
4566 newsrv->state &= ~SRV_TPROXY_MASK;
4567 newsrv->state |= SRV_TPROXY_DYN;
4568 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4569 newsrv->bind_hdr_len = end - name;
4570 memcpy(newsrv->bind_hdr_name, name, end - name);
4571 newsrv->bind_hdr_name[end-name] = '\0';
4572 newsrv->bind_hdr_occ = -1;
4573
4574 /* now look for an occurrence number */
4575 while (isspace(*end))
4576 end++;
4577 if (*end == ',') {
4578 end++;
4579 name = end;
4580 if (*end == '-')
4581 end++;
4582 while (isdigit(*end))
4583 end++;
4584 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4585 }
4586
4587 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4588 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4589 " occurrences values smaller than %d.\n",
4590 file, linenum, MAX_HDR_HISTORY);
4591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
4593 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004594 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004595 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004596 if (!sk) {
4597 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004602 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004603 }
4604 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004605#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004606 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004607#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004608 cur_arg += 2;
4609 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004610#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004611 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004612 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004615#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4616 } /* "usesrc" */
4617
4618 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4619#ifdef SO_BINDTODEVICE
4620 if (!*args[cur_arg + 1]) {
4621 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004625 }
4626 if (newsrv->iface_name)
4627 free(newsrv->iface_name);
4628
4629 newsrv->iface_name = strdup(args[cur_arg + 1]);
4630 newsrv->iface_len = strlen(newsrv->iface_name);
4631 global.last_checks |= LSTCHK_NETADM;
4632#else
4633 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4634 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004637#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004638 cur_arg += 2;
4639 continue;
4640 }
4641 /* this keyword in not an option of "source" */
4642 break;
4643 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004645 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004646 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4647 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004652 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004653 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 +01004654 file, linenum, newsrv->id);
4655 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004656 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 +01004657 file, linenum);
4658
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
4662 }
4663
4664 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004665 if (newsrv->trackit) {
4666 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4667 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004670 }
4671
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004672 /* try to get the port from check_addr if check_port not set */
4673 if (!newsrv->check_port)
4674 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004675
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4677 newsrv->check_port = realport; /* by default */
4678 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004679 /* not yet valid, because no port was set on
4680 * the server either. We'll check if we have
4681 * a known port on the first listener.
4682 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004683 struct listener *l = curproxy->listen;
4684 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4685 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004686 }
4687 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4689 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004693
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004694 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004695 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004696 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4697 err_code |= ERR_ALERT | ERR_ABORT;
4698 goto out;
4699 }
4700
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004701 /* Allocate buffer for partial check results... */
4702 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4703 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4704 err_code |= ERR_ALERT | ERR_ABORT;
4705 goto out;
4706 }
4707
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004708 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 newsrv->state |= SRV_CHECKED;
4710 }
4711
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004712 if (!defsrv) {
4713 if (newsrv->state & SRV_BACKUP)
4714 curproxy->srv_bck++;
4715 else
4716 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004717
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004718 newsrv->prev_state = newsrv->state;
4719 }
William Lallemanda73203e2012-03-12 12:48:57 +01004720 }
4721
4722 else if (strcmp(args[0], "unique-id-format") == 0) {
4723 if (!*(args[1])) {
4724 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
4727 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004728 free(curproxy->uniqueid_format_string);
4729 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004730 }
William Lallemanda73203e2012-03-12 12:48:57 +01004731
4732 else if (strcmp(args[0], "unique-id-header") == 0) {
4733 if (!*(args[1])) {
4734 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
4738 free(curproxy->header_unique_id);
4739 curproxy->header_unique_id = strdup(args[1]);
4740 }
4741
William Lallemand723b73a2012-02-08 16:37:49 +01004742 else if (strcmp(args[0], "log-format") == 0) {
4743 if (!*(args[1])) {
4744 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004748
4749 if (curproxy->logformat_string != default_http_log_format &&
4750 curproxy->logformat_string != default_tcp_log_format &&
4751 curproxy->logformat_string != clf_http_log_format)
4752 free(curproxy->logformat_string);
4753 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
William Lallemand723b73a2012-02-08 16:37:49 +01004755
William Lallemand0f99e342011-10-12 17:50:54 +02004756 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4757 /* delete previous herited or defined syslog servers */
4758 struct logsrv *back;
4759
4760 if (*(args[1]) != 0) {
4761 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
4764 }
4765
William Lallemand723b73a2012-02-08 16:37:49 +01004766 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4767 LIST_DEL(&tmplogsrv->list);
4768 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004769 }
4770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004772 struct logsrv *logsrv;
4773
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004775 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004776 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004777 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004778 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004779 LIST_INIT(&node->list);
4780 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 }
4783 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004784
4785 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786
William Lallemand0f99e342011-10-12 17:50:54 +02004787 logsrv->facility = get_log_facility(args[2]);
4788 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
4794
William Lallemand0f99e342011-10-12 17:50:54 +02004795 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004797 logsrv->level = get_log_level(args[3]);
4798 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 }
4804 }
4805
William Lallemand0f99e342011-10-12 17:50:54 +02004806 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004807 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004808 logsrv->minlvl = get_log_level(args[4]);
4809 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004810 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004814 }
4815 }
4816
Robert Tsai81ae1952007-12-05 10:47:29 +01004817 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004818 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004819 if (!sk) {
4820 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004821 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
William Lallemand0f99e342011-10-12 17:50:54 +02004825 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004826 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004827 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004828 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004829 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
William Lallemand0f99e342011-10-12 17:50:54 +02004833 logsrv->addr = *sk;
4834 if (!get_host_port(&logsrv->addr))
4835 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
William Lallemand0f99e342011-10-12 17:50:54 +02004837
4838 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 }
4840 else {
4841 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4842 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
4846 }
4847 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004848 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004849 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004850
Willy Tarreau977b8e42006-12-29 14:19:17 +01004851 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004853
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004855 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4856 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004860
4861 /* we must first clear any optional default setting */
4862 curproxy->options &= ~PR_O_TPXY_MASK;
4863 free(curproxy->iface_name);
4864 curproxy->iface_name = NULL;
4865 curproxy->iface_len = 0;
4866
Willy Tarreaud5191e72010-02-09 20:50:45 +01004867 sk = str2sa(args[1]);
4868 if (!sk) {
4869 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875
4876 cur_arg = 2;
4877 while (*(args[cur_arg])) {
4878 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004879#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4880#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004881 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4882 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4883 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004886 }
4887#endif
4888 if (!*args[cur_arg + 1]) {
4889 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4890 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 }
4894
4895 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004896 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004897 curproxy->options |= PR_O_TPXY_CLI;
4898 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004899 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004900 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004901 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4902 char *name, *end;
4903
4904 name = args[cur_arg+1] + 7;
4905 while (isspace(*name))
4906 name++;
4907
4908 end = name;
4909 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4910 end++;
4911
4912 curproxy->options &= ~PR_O_TPXY_MASK;
4913 curproxy->options |= PR_O_TPXY_DYN;
4914 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4915 curproxy->bind_hdr_len = end - name;
4916 memcpy(curproxy->bind_hdr_name, name, end - name);
4917 curproxy->bind_hdr_name[end-name] = '\0';
4918 curproxy->bind_hdr_occ = -1;
4919
4920 /* now look for an occurrence number */
4921 while (isspace(*end))
4922 end++;
4923 if (*end == ',') {
4924 end++;
4925 name = end;
4926 if (*end == '-')
4927 end++;
4928 while (isdigit(*end))
4929 end++;
4930 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4931 }
4932
4933 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4934 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4935 " occurrences values smaller than %d.\n",
4936 file, linenum, MAX_HDR_HISTORY);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004940 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004941 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004942 if (!sk) {
4943 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
4946 }
4947 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004949 }
4950 global.last_checks |= LSTCHK_NETADM;
4951#if !defined(CONFIG_HAP_LINUX_TPROXY)
4952 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004953#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004954#else /* no TPROXY support */
4955 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004956 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959#endif
4960 cur_arg += 2;
4961 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004962 }
4963
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004964 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4965#ifdef SO_BINDTODEVICE
4966 if (!*args[cur_arg + 1]) {
4967 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4968 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004971 }
4972 if (curproxy->iface_name)
4973 free(curproxy->iface_name);
4974
4975 curproxy->iface_name = strdup(args[cur_arg + 1]);
4976 curproxy->iface_len = strlen(curproxy->iface_name);
4977 global.last_checks |= LSTCHK_NETADM;
4978#else
4979 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4980 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004983#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004984 cur_arg += 2;
4985 continue;
4986 }
4987 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4988 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004993 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4994 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4995 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5002 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006
5007 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005008 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005009 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 }
5013 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005014 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005015 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005016 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
5020 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005022 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005023 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
5027 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005029 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005030 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
5034 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005036 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005037 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005041 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005043 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005044 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005046 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005047 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005048 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005050 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005051 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005053 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005054 }
5055 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005057 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005058 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005060 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5065 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069
5070 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005071 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005072 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
5076 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005078 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005079 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005085 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005086 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005092 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005093 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
5097 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005099 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005100 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005104 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005112 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005113
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 if (curproxy == &defproxy) {
5115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005119 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 if (*(args[1]) == 0) {
5123 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005127
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005128 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005129 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5130 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5131 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5136 }
5137 else if (*args[2]) {
5138 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5139 file, linenum, args[0], args[2]);
5140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
5143
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005144 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005145 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005146 wl->s = strdup(args[1]);
5147 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005148 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005159 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005160 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 }
5164 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005166 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005167 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005170 }
5171 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005173 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005174 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
5178 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
5185
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005187 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005188 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005194 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
5199 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005202 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005207 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005208
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 if (curproxy == &defproxy) {
5210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005214 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 if (*(args[1]) == 0) {
5218 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
5222
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005223 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005224 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5225 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5226 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 err_code |= warnif_cond_requires_req(cond, file, linenum);
5231 }
5232 else if (*args[2]) {
5233 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5234 file, linenum, args[0], args[2]);
5235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237 }
5238
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005239 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005240 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005241 wl->s = strdup(args[1]);
5242 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
5244 else if (!strcmp(args[0], "errorloc") ||
5245 !strcmp(args[0], "errorloc302") ||
5246 !strcmp(args[0], "errorloc303")) { /* error location */
5247 int errnum, errlen;
5248 char *err;
5249
Willy Tarreau977b8e42006-12-29 14:19:17 +01005250 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005252
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005254 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
5258
5259 errnum = atol(args[1]);
5260 if (!strcmp(args[0], "errorloc303")) {
5261 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5262 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5263 } else {
5264 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5265 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5266 }
5267
Willy Tarreau0f772532006-12-23 20:51:41 +01005268 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5269 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005270 chunk_destroy(&curproxy->errmsg[rc]);
5271 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005272 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005275
5276 if (rc >= HTTP_ERR_SIZE) {
5277 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5278 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 free(err);
5280 }
5281 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005282 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5283 int errnum, errlen, fd;
5284 char *err;
5285 struct stat stat;
5286
5287 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005288 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005289
5290 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005291 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005294 }
5295
5296 fd = open(args[2], O_RDONLY);
5297 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5298 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5299 file, linenum, args[2], args[1]);
5300 if (fd >= 0)
5301 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005304 }
5305
Willy Tarreau27a674e2009-08-17 07:23:33 +02005306 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005307 errlen = stat.st_size;
5308 } else {
5309 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005310 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005312 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005313 }
5314
5315 err = malloc(errlen); /* malloc() must succeed during parsing */
5316 errnum = read(fd, err, errlen);
5317 if (errnum != errlen) {
5318 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5319 file, linenum, args[2], args[1]);
5320 close(fd);
5321 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005324 }
5325 close(fd);
5326
5327 errnum = atol(args[1]);
5328 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5329 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005330 chunk_destroy(&curproxy->errmsg[rc]);
5331 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005332 break;
5333 }
5334 }
5335
5336 if (rc >= HTTP_ERR_SIZE) {
5337 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5338 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005340 free(err);
5341 }
5342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005344 struct cfg_kw_list *kwl;
5345 int index;
5346
5347 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5348 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5349 if (kwl->kw[index].section != CFG_LISTEN)
5350 continue;
5351 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5352 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005353 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005354 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005355 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005356 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005357 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005360 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005361 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005362 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005363 err_code |= ERR_WARN;
5364 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005365 }
Willy Tarreau93893792009-07-23 13:19:11 +02005366 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005367 }
5368 }
5369 }
5370
Willy Tarreau6daf3432008-01-22 16:44:08 +01005371 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
Willy Tarreau93893792009-07-23 13:19:11 +02005375 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005376 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005377 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378}
5379
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005380int
5381cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5382{
5383
5384 int err_code = 0;
5385 const char *err;
5386
5387 if (!strcmp(args[0], "userlist")) { /* new userlist */
5388 struct userlist *newul;
5389
5390 if (!*args[1]) {
5391 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5392 file, linenum, args[0]);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396
5397 err = invalid_char(args[1]);
5398 if (err) {
5399 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5400 file, linenum, *err, args[0], args[1]);
5401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
5403 }
5404
5405 for (newul = userlist; newul; newul = newul->next)
5406 if (!strcmp(newul->name, args[1])) {
5407 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5408 file, linenum, args[1]);
5409 err_code |= ERR_WARN;
5410 goto out;
5411 }
5412
5413 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5414 if (!newul) {
5415 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5416 err_code |= ERR_ALERT | ERR_ABORT;
5417 goto out;
5418 }
5419
5420 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5421 newul->name = strdup(args[1]);
5422
5423 if (!newul->groupusers | !newul->name) {
5424 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5425 err_code |= ERR_ALERT | ERR_ABORT;
5426 goto out;
5427 }
5428
5429 newul->next = userlist;
5430 userlist = newul;
5431
5432 } else if (!strcmp(args[0], "group")) { /* new group */
5433 int cur_arg, i;
5434 const char *err;
5435
5436 if (!*args[1]) {
5437 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5438 file, linenum, args[0]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
5443 err = invalid_char(args[1]);
5444 if (err) {
5445 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5446 file, linenum, *err, args[0], args[1]);
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 }
5450
5451 for(i = 0; i < userlist->grpcnt; i++)
5452 if (!strcmp(userlist->groups[i], args[1])) {
5453 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5454 file, linenum, args[1], userlist->name);
5455 err_code |= ERR_ALERT;
5456 goto out;
5457 }
5458
5459 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5460 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5461 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465
5466 cur_arg = 2;
5467
5468 while (*args[cur_arg]) {
5469 if (!strcmp(args[cur_arg], "users")) {
5470 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5471 cur_arg += 2;
5472 continue;
5473 } else {
5474 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5475 file, linenum, args[0]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
5479 }
5480
5481 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5482 } else if (!strcmp(args[0], "user")) { /* new user */
5483 struct auth_users *newuser;
5484 int cur_arg;
5485
5486 if (!*args[1]) {
5487 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5488 file, linenum, args[0]);
5489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 }
5492
5493 for (newuser = userlist->users; newuser; newuser = newuser->next)
5494 if (!strcmp(newuser->user, args[1])) {
5495 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5496 file, linenum, args[1], userlist->name);
5497 err_code |= ERR_ALERT;
5498 goto out;
5499 }
5500
5501 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5502 if (!newuser) {
5503 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5504 err_code |= ERR_ALERT | ERR_ABORT;
5505 goto out;
5506 }
5507
5508 newuser->user = strdup(args[1]);
5509
5510 newuser->next = userlist->users;
5511 userlist->users = newuser;
5512
5513 cur_arg = 2;
5514
5515 while (*args[cur_arg]) {
5516 if (!strcmp(args[cur_arg], "password")) {
5517#ifndef CONFIG_HAP_CRYPT
5518 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5519 file, linenum);
5520 err_code |= ERR_ALERT;
5521#endif
5522 newuser->pass = strdup(args[cur_arg + 1]);
5523 cur_arg += 2;
5524 continue;
5525 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5526 newuser->pass = strdup(args[cur_arg + 1]);
5527 newuser->flags |= AU_O_INSECURE;
5528 cur_arg += 2;
5529 continue;
5530 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005531 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005532 cur_arg += 2;
5533 continue;
5534 } else {
5535 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5536 file, linenum, args[0]);
5537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
5539 }
5540 }
5541 } else {
5542 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 }
5545
5546out:
5547 return err_code;
5548}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549
5550/*
5551 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005552 * Returns the error code, 0 if OK, or any combination of :
5553 * - ERR_ABORT: must abort ASAP
5554 * - ERR_FATAL: we can continue parsing but not start the service
5555 * - ERR_WARN: a warning has been emitted
5556 * - ERR_ALERT: an alert has been emitted
5557 * Only the two first ones can stop processing, the two others are just
5558 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005560int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005562 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 FILE *f;
5564 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005566 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 if ((f=fopen(file,"r")) == NULL)
5569 return -1;
5570
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005571 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005572 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005573 char *end;
5574 char *args[MAX_LINE_ARGS + 1];
5575 char *line = thisline;
5576
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 linenum++;
5578
5579 end = line + strlen(line);
5580
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005581 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5582 /* Check if we reached the limit and the last char is not \n.
5583 * Watch out for the last line without the terminating '\n'!
5584 */
5585 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005586 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005588 }
5589
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005591 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 line++;
5593
5594 arg = 0;
5595 args[arg] = line;
5596
5597 while (*line && arg < MAX_LINE_ARGS) {
5598 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5599 * C equivalent value. Other combinations left unchanged (eg: \1).
5600 */
5601 if (*line == '\\') {
5602 int skip = 0;
5603 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5604 *line = line[1];
5605 skip = 1;
5606 }
5607 else if (line[1] == 'r') {
5608 *line = '\r';
5609 skip = 1;
5610 }
5611 else if (line[1] == 'n') {
5612 *line = '\n';
5613 skip = 1;
5614 }
5615 else if (line[1] == 't') {
5616 *line = '\t';
5617 skip = 1;
5618 }
5619 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005620 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 unsigned char hex1, hex2;
5622 hex1 = toupper(line[2]) - '0';
5623 hex2 = toupper(line[3]) - '0';
5624 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5625 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5626 *line = (hex1<<4) + hex2;
5627 skip = 3;
5628 }
5629 else {
5630 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 }
5633 }
5634 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005635 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 end -= skip;
5637 }
5638 line++;
5639 }
5640 else if (*line == '#' || *line == '\n' || *line == '\r') {
5641 /* end of string, end of loop */
5642 *line = 0;
5643 break;
5644 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005645 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005646 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005647 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005648 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 line++;
5650 args[++arg] = line;
5651 }
5652 else {
5653 line++;
5654 }
5655 }
5656
5657 /* empty line */
5658 if (!**args)
5659 continue;
5660
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005661 if (*line) {
5662 /* we had to stop due to too many args.
5663 * Let's terminate the string, print the offending part then cut the
5664 * last arg.
5665 */
5666 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5667 line++;
5668 *line = '\0';
5669
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005670 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005671 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 args[arg] = line;
5674 }
5675
Willy Tarreau540abe42007-05-02 20:50:16 +02005676 /* zero out remaining args and ensure that at least one entry
5677 * is zeroed out.
5678 */
5679 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 args[arg] = line;
5681 }
5682
Willy Tarreau3842f002009-06-14 11:39:52 +02005683 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005684 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005685 char *tmp;
5686
Willy Tarreau3842f002009-06-14 11:39:52 +02005687 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005688 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005689 for (arg=0; *args[arg+1]; arg++)
5690 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005691 *tmp = '\0'; // fix the next arg to \0
5692 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005693 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005694 else if (!strcmp(args[0], "default")) {
5695 kwm = KWM_DEF;
5696 for (arg=0; *args[arg+1]; arg++)
5697 args[arg] = args[arg+1]; // shift args after inversion
5698 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005699
William Lallemand0f99e342011-10-12 17:50:54 +02005700 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5701 strcmp(args[0], "log") != 0) {
5702 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005704 }
5705
Willy Tarreau977b8e42006-12-29 14:19:17 +01005706 if (!strcmp(args[0], "listen") ||
5707 !strcmp(args[0], "frontend") ||
5708 !strcmp(args[0], "backend") ||
5709 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005710 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005712 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005713 cursection = strdup(args[0]);
5714 }
5715 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005717 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005718 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005719 }
5720 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005721 confsect = CFG_USERLIST;
5722 free(cursection);
5723 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005724 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005725 else if (!strcmp(args[0], "peers")) {
5726 confsect = CFG_PEERS;
5727 free(cursection);
5728 cursection = strdup(args[0]);
5729 }
5730
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 /* else it's a section keyword */
5732
5733 switch (confsect) {
5734 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 break;
5737 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005738 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005740 case CFG_USERLIST:
5741 err_code |= cfg_parse_users(file, linenum, args, kwm);
5742 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005743 case CFG_PEERS:
5744 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5745 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005747 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005750
5751 if (err_code & ERR_ABORT)
5752 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005754 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005755 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005757 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005758}
5759
Willy Tarreaubb925012009-07-23 13:36:36 +02005760/*
5761 * Returns the error code, 0 if OK, or any combination of :
5762 * - ERR_ABORT: must abort ASAP
5763 * - ERR_FATAL: we can continue parsing but not start the service
5764 * - ERR_WARN: a warning has been emitted
5765 * - ERR_ALERT: an alert has been emitted
5766 * Only the two first ones can stop processing, the two others are just
5767 * indicators.
5768 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005769int check_config_validity()
5770{
5771 int cfgerr = 0;
5772 struct proxy *curproxy = NULL;
5773 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005774 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005775 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005776 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777
5778 /*
5779 * Now, check for the integrity of all that we have collected.
5780 */
5781
5782 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005783 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005785 /* first, we will invert the proxy list order */
5786 curproxy = NULL;
5787 while (proxy) {
5788 struct proxy *next;
5789
5790 next = proxy->next;
5791 proxy->next = curproxy;
5792 curproxy = proxy;
5793 if (!next)
5794 break;
5795 proxy = next;
5796 }
5797
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005799 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005800 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005801 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005802 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005803 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005804 unsigned int next_id;
5805
5806 if (!curproxy->uuid) {
5807 /* proxy ID not set, use automatic numbering with first
5808 * spare entry starting with next_pxid.
5809 */
5810 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5811 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5812 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005813 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005814 next_pxid++;
5815
Willy Tarreau55ea7572007-06-17 19:56:27 +02005816
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005818 /* ensure we don't keep listeners uselessly bound */
5819 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 curproxy = curproxy->next;
5821 continue;
5822 }
5823
Willy Tarreauff01a212009-03-15 13:46:16 +01005824 switch (curproxy->mode) {
5825 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005826 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005827 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005828 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5829 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005830 cfgerr++;
5831 }
5832
5833 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005834 Warning("config : servers will be ignored for %s '%s'.\n",
5835 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005836 break;
5837
5838 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005839 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005840 break;
5841
5842 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005843 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005844 break;
5845 }
5846
5847 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005848 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5849 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 cfgerr++;
5851 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005852
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005853 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005854 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005855 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005856 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5857 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005858 cfgerr++;
5859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005861 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005862 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5863 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005864 cfgerr++;
5865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005867 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005868 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5869 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005870 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005871 }
5872 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005873 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005874 /* If no LB algo is set in a backend, and we're not in
5875 * transparent mode, dispatch mode nor proxy mode, we
5876 * want to use balance roundrobin by default.
5877 */
5878 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5879 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
5881 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005882
Willy Tarreau1620ec32011-08-06 17:05:02 +02005883 if (curproxy->options & PR_O_DISPATCH)
5884 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5885 else if (curproxy->options & PR_O_HTTP_PROXY)
5886 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5887 else if (curproxy->options & PR_O_TRANSP)
5888 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005889
Willy Tarreau1620ec32011-08-06 17:05:02 +02005890 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5891 if (curproxy->options & PR_O_DISABLE404) {
5892 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5893 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5894 err_code |= ERR_WARN;
5895 curproxy->options &= ~PR_O_DISABLE404;
5896 }
5897 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5898 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5899 "send-state", proxy_type_str(curproxy), curproxy->id);
5900 err_code |= ERR_WARN;
5901 curproxy->options &= ~PR_O2_CHK_SNDST;
5902 }
Willy Tarreauef781042010-01-27 11:53:01 +01005903 }
5904
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005905 /* if a default backend was specified, let's find it */
5906 if (curproxy->defbe.name) {
5907 struct proxy *target;
5908
Alex Williams96532db2009-11-01 21:27:13 -05005909 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005910 if (!target) {
5911 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5912 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005913 cfgerr++;
5914 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005915 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5916 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005917 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005918 } else {
5919 free(curproxy->defbe.name);
5920 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005921 /* we force the backend to be present on at least all of
5922 * the frontend's processes.
5923 */
5924 target->bind_proc = curproxy->bind_proc ?
5925 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005926
5927 /* Emit a warning if this proxy also has some servers */
5928 if (curproxy->srv) {
5929 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5930 curproxy->id);
5931 err_code |= ERR_WARN;
5932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 }
5934 }
5935
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005936 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005937 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5938 /* map jump target for ACT_SETBE in req_rep chain */
5939 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005940 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005941 struct proxy *target;
5942
Willy Tarreaua496b602006-12-17 23:15:24 +01005943 if (exp->action != ACT_SETBE)
5944 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005945
Alex Williams96532db2009-11-01 21:27:13 -05005946 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005947 if (!target) {
5948 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5949 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005950 cfgerr++;
5951 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005952 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5953 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005954 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005955 } else {
5956 free((void *)exp->replace);
5957 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005958 /* we force the backend to be present on at least all of
5959 * the frontend's processes.
5960 */
5961 target->bind_proc = curproxy->bind_proc ?
5962 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005963 }
5964 }
5965 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005966
5967 /* find the target proxy for 'use_backend' rules */
5968 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005969 struct proxy *target;
5970
Alex Williams96532db2009-11-01 21:27:13 -05005971 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005972
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005973 if (!target) {
5974 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5975 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005976 cfgerr++;
5977 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005978 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5979 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005980 cfgerr++;
5981 } else {
5982 free((void *)rule->be.name);
5983 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005984 /* we force the backend to be present on at least all of
5985 * the frontend's processes.
5986 */
5987 target->bind_proc = curproxy->bind_proc ?
5988 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005989 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005990 }
5991
5992 /* find the target proxy for 'use_backend' rules */
5993 list_for_each_entry(srule, &curproxy->server_rules, list) {
5994 struct server *target = findserver(curproxy, srule->srv.name);
5995
5996 if (!target) {
5997 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5998 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5999 cfgerr++;
6000 continue;
6001 }
6002 free((void *)srule->srv.name);
6003 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006004 }
6005
Emeric Brunb982a3d2010-01-04 15:45:53 +01006006 /* find the target table for 'stick' rules */
6007 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6008 struct proxy *target;
6009
Emeric Brun1d33b292010-01-04 15:47:17 +01006010 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6011 if (mrule->flags & STK_IS_STORE)
6012 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6013
Emeric Brunb982a3d2010-01-04 15:45:53 +01006014 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006015 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006016 else
6017 target = curproxy;
6018
6019 if (!target) {
6020 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6021 curproxy->id, mrule->table.name);
6022 cfgerr++;
6023 }
6024 else if (target->table.size == 0) {
6025 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6026 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6027 cfgerr++;
6028 }
Willy Tarreau12785782012-04-27 21:37:17 +02006029 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6030 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006031 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6032 cfgerr++;
6033 }
6034 else {
6035 free((void *)mrule->table.name);
6036 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006037 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006038 }
6039 }
6040
6041 /* find the target table for 'store response' rules */
6042 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6043 struct proxy *target;
6044
Emeric Brun1d33b292010-01-04 15:47:17 +01006045 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6046
Emeric Brunb982a3d2010-01-04 15:45:53 +01006047 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006048 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006049 else
6050 target = curproxy;
6051
6052 if (!target) {
6053 Alert("Proxy '%s': unable to find store table '%s'.\n",
6054 curproxy->id, mrule->table.name);
6055 cfgerr++;
6056 }
6057 else if (target->table.size == 0) {
6058 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6059 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6060 cfgerr++;
6061 }
Willy Tarreau12785782012-04-27 21:37:17 +02006062 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6063 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006064 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6065 cfgerr++;
6066 }
6067 else {
6068 free((void *)mrule->table.name);
6069 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006070 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006071 }
6072 }
6073
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006074 /* find the target table for 'tcp-request' layer 4 rules */
6075 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6076 struct proxy *target;
6077
Willy Tarreau56123282010-08-06 19:06:56 +02006078 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006079 continue;
6080
6081 if (trule->act_prm.trk_ctr.table.n)
6082 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6083 else
6084 target = curproxy;
6085
6086 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006087 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6088 curproxy->id, trule->act_prm.trk_ctr.table.n,
6089 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006090 cfgerr++;
6091 }
6092 else if (target->table.size == 0) {
6093 Alert("Proxy '%s': table '%s' used but not configured.\n",
6094 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6095 cfgerr++;
6096 }
6097 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006098 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 +02006099 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6100 cfgerr++;
6101 }
6102 else {
6103 free(trule->act_prm.trk_ctr.table.n);
6104 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006105 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006106 * to pass a list of counters to track and allocate them right here using
6107 * stktable_alloc_data_type().
6108 */
6109 }
6110 }
6111
Willy Tarreaud1f96522010-08-03 19:34:32 +02006112 /* find the target table for 'tcp-request' layer 6 rules */
6113 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6114 struct proxy *target;
6115
Willy Tarreau56123282010-08-06 19:06:56 +02006116 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006117 continue;
6118
6119 if (trule->act_prm.trk_ctr.table.n)
6120 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6121 else
6122 target = curproxy;
6123
6124 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006125 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6126 curproxy->id, trule->act_prm.trk_ctr.table.n,
6127 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006128 cfgerr++;
6129 }
6130 else if (target->table.size == 0) {
6131 Alert("Proxy '%s': table '%s' used but not configured.\n",
6132 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6133 cfgerr++;
6134 }
6135 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006136 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 +02006137 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6138 cfgerr++;
6139 }
6140 else {
6141 free(trule->act_prm.trk_ctr.table.n);
6142 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006143 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006144 * to pass a list of counters to track and allocate them right here using
6145 * stktable_alloc_data_type().
6146 */
6147 }
6148 }
6149
Emeric Brun32da3c42010-09-23 18:39:19 +02006150 if (curproxy->table.peers.name) {
6151 struct peers *curpeers = peers;
6152
6153 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6154 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6155 free((void *)curproxy->table.peers.name);
6156 curproxy->table.peers.p = peers;
6157 break;
6158 }
6159 }
6160
6161 if (!curpeers) {
6162 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6163 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006164 free((void *)curproxy->table.peers.name);
6165 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006166 cfgerr++;
6167 }
6168 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006169 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6170 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006171 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006172 cfgerr++;
6173 }
6174 }
6175
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006176 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006177 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006178 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6179 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6180 "proxy", curproxy->id);
6181 cfgerr++;
6182 goto out_uri_auth_compat;
6183 }
6184
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006185 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006186 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006187 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006188 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006189
Willy Tarreau95fa4692010-02-01 13:05:50 +01006190 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6191 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006192
6193 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006194 uri_auth_compat_req[i++] = "realm";
6195 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6196 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006197
Willy Tarreau95fa4692010-02-01 13:05:50 +01006198 uri_auth_compat_req[i++] = "unless";
6199 uri_auth_compat_req[i++] = "{";
6200 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6201 uri_auth_compat_req[i++] = "}";
6202 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006203
Willy Tarreauff011f22011-01-06 17:51:27 +01006204 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6205 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006206 cfgerr++;
6207 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006208 }
6209
Willy Tarreauff011f22011-01-06 17:51:27 +01006210 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006211
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006212 if (curproxy->uri_auth->auth_realm) {
6213 free(curproxy->uri_auth->auth_realm);
6214 curproxy->uri_auth->auth_realm = NULL;
6215 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006216
6217 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006218 }
6219out_uri_auth_compat:
6220
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006221 cfgerr += acl_find_targets(curproxy);
6222
Willy Tarreau2738a142006-07-08 17:28:09 +02006223 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006224 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006225 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006226 (!curproxy->timeout.connect ||
6227 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006229 " | While not properly invalid, you will certainly encounter various problems\n"
6230 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006231 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006232 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006233 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006234 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006235
Willy Tarreau1fa31262007-12-03 00:36:16 +01006236 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6237 * We must still support older configurations, so let's find out whether those
6238 * parameters have been set or must be copied from contimeouts.
6239 */
6240 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006241 if (!curproxy->timeout.tarpit ||
6242 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006243 /* tarpit timeout not set. We search in the following order:
6244 * default.tarpit, curr.connect, default.connect.
6245 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006246 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006247 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006248 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006249 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006250 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006251 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006252 }
6253 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006254 (!curproxy->timeout.queue ||
6255 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006256 /* queue timeout not set. We search in the following order:
6257 * default.queue, curr.connect, default.connect.
6258 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006259 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006260 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006261 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006262 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006263 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006264 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006265 }
6266 }
6267
Willy Tarreau1620ec32011-08-06 17:05:02 +02006268 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006269 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6270 curproxy->check_req = (char *)malloc(curproxy->check_len);
6271 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006272 }
6273
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006274 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006275 if (curproxy->nb_req_cap) {
6276 if (curproxy->mode == PR_MODE_HTTP) {
6277 curproxy->req_cap_pool = create_pool("ptrcap",
6278 curproxy->nb_req_cap * sizeof(char *),
6279 MEM_F_SHARED);
6280 } else {
6281 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6282 proxy_type_str(curproxy), curproxy->id);
6283 err_code |= ERR_WARN;
6284 curproxy->to_log &= ~LW_REQHDR;
6285 curproxy->nb_req_cap = 0;
6286 }
6287 }
6288
6289 if (curproxy->nb_rsp_cap) {
6290 if (curproxy->mode == PR_MODE_HTTP) {
6291 curproxy->rsp_cap_pool = create_pool("ptrcap",
6292 curproxy->nb_rsp_cap * sizeof(char *),
6293 MEM_F_SHARED);
6294 } else {
6295 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6296 proxy_type_str(curproxy), curproxy->id);
6297 err_code |= ERR_WARN;
6298 curproxy->to_log &= ~LW_REQHDR;
6299 curproxy->nb_rsp_cap = 0;
6300 }
6301 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006302
Willy Tarreau196729e2012-05-31 19:30:26 +02006303 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006304 if (!(curproxy->cap & PR_CAP_FE)) {
6305 if (curproxy->logformat_string != default_http_log_format &&
6306 curproxy->logformat_string != default_tcp_log_format &&
6307 curproxy->logformat_string != clf_http_log_format)
6308 free(curproxy->logformat_string);
6309 curproxy->logformat_string = NULL;
6310 }
6311
Willy Tarreau196729e2012-05-31 19:30:26 +02006312 if (curproxy->logformat_string)
6313 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6314
6315 if (curproxy->uniqueid_format_string)
6316 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6317
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 /* first, we will invert the servers list order */
6319 newsrv = NULL;
6320 while (curproxy->srv) {
6321 struct server *next;
6322
6323 next = curproxy->srv->next;
6324 curproxy->srv->next = newsrv;
6325 newsrv = curproxy->srv;
6326 if (!next)
6327 break;
6328 curproxy->srv = next;
6329 }
6330
Willy Tarreaudd701652010-05-25 23:03:02 +02006331 /* assign automatic UIDs to servers which don't have one yet */
6332 next_id = 1;
6333 newsrv = curproxy->srv;
6334 while (newsrv != NULL) {
6335 if (!newsrv->puid) {
6336 /* server ID not set, use automatic numbering with first
6337 * spare entry starting with next_svid.
6338 */
6339 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6340 newsrv->conf.id.key = newsrv->puid = next_id;
6341 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6342 }
6343 next_id++;
6344 newsrv = newsrv->next;
6345 }
6346
Willy Tarreau20697042007-11-15 23:26:18 +01006347 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006348 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349
Willy Tarreau62c3be22012-01-20 13:12:32 +01006350 /*
6351 * If this server supports a maxconn parameter, it needs a dedicated
6352 * tasks to fill the emptied slots when a connection leaves.
6353 * Also, resolve deferred tracking dependency if needed.
6354 */
6355 newsrv = curproxy->srv;
6356 while (newsrv != NULL) {
6357 if (newsrv->minconn > newsrv->maxconn) {
6358 /* Only 'minconn' was specified, or it was higher than or equal
6359 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6360 * this will avoid further useless expensive computations.
6361 */
6362 newsrv->maxconn = newsrv->minconn;
6363 } else if (newsrv->maxconn && !newsrv->minconn) {
6364 /* minconn was not specified, so we set it to maxconn */
6365 newsrv->minconn = newsrv->maxconn;
6366 }
6367
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006368#ifdef USE_OPENSSL
6369#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6370#define SSL_OP_NO_COMPRESSION 0
6371#endif
6372#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6373#define SSL_MODE_RELEASE_BUFFERS 0
6374#endif
6375#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6376#define SSL_OP_NO_COMPRESSION 0
6377#endif
6378 if (newsrv->use_ssl) {
6379 int ssloptions =
6380 SSL_OP_ALL | /* all known workarounds for bugs */
6381 SSL_OP_NO_SSLv2 |
6382 SSL_OP_NO_COMPRESSION;
6383 int sslmode =
6384 SSL_MODE_ENABLE_PARTIAL_WRITE |
6385 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6386 SSL_MODE_RELEASE_BUFFERS;
6387
6388 /* Initiate SSL context for current server */
6389 newsrv->ssl_ctx.reused_sess = NULL;
6390 newsrv->data = &ssl_sock;
6391 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6392 if(!newsrv->ssl_ctx.ctx) {
6393
6394 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6395 proxy_type_str(curproxy), curproxy->id,
6396 newsrv->id);
6397 cfgerr++;
6398 goto next_srv;
6399 }
6400
6401 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6402 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6403 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6404 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
6405 }
6406#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006407 if (newsrv->trackit) {
6408 struct proxy *px;
6409 struct server *srv;
6410 char *pname, *sname;
6411
6412 pname = newsrv->trackit;
6413 sname = strrchr(pname, '/');
6414
6415 if (sname)
6416 *sname++ = '\0';
6417 else {
6418 sname = pname;
6419 pname = NULL;
6420 }
6421
6422 if (pname) {
6423 px = findproxy(pname, PR_CAP_BE);
6424 if (!px) {
6425 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6426 proxy_type_str(curproxy), curproxy->id,
6427 newsrv->id, pname);
6428 cfgerr++;
6429 goto next_srv;
6430 }
6431 } else
6432 px = curproxy;
6433
6434 srv = findserver(px, sname);
6435 if (!srv) {
6436 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6437 proxy_type_str(curproxy), curproxy->id,
6438 newsrv->id, sname);
6439 cfgerr++;
6440 goto next_srv;
6441 }
6442
6443 if (!(srv->state & SRV_CHECKED)) {
6444 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6445 "tracking as it does not have checks enabled.\n",
6446 proxy_type_str(curproxy), curproxy->id,
6447 newsrv->id, px->id, srv->id);
6448 cfgerr++;
6449 goto next_srv;
6450 }
6451
6452 if (curproxy != px &&
6453 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6454 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6455 "tracking: disable-on-404 option inconsistency.\n",
6456 proxy_type_str(curproxy), curproxy->id,
6457 newsrv->id, px->id, srv->id);
6458 cfgerr++;
6459 goto next_srv;
6460 }
6461
6462 /* if the other server is forced disabled, we have to do the same here */
6463 if (srv->state & SRV_MAINTAIN) {
6464 newsrv->state |= SRV_MAINTAIN;
6465 newsrv->state &= ~SRV_RUNNING;
6466 newsrv->health = 0;
6467 }
6468
6469 newsrv->track = srv;
6470 newsrv->tracknext = srv->tracknext;
6471 srv->tracknext = newsrv;
6472
6473 free(newsrv->trackit);
6474 newsrv->trackit = NULL;
6475 }
6476 next_srv:
6477 newsrv = newsrv->next;
6478 }
6479
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006480 /* We have to initialize the server lookup mechanism depending
6481 * on what LB algorithm was choosen.
6482 */
6483
6484 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6485 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6486 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006487 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6488 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6489 init_server_map(curproxy);
6490 } else {
6491 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6492 fwrr_init_server_groups(curproxy);
6493 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006494 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006495
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006496 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006497 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6498 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6499 fwlc_init_server_tree(curproxy);
6500 } else {
6501 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6502 fas_init_server_tree(curproxy);
6503 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006504 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006505
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006506 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006507 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6508 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6509 chash_init_server_tree(curproxy);
6510 } else {
6511 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6512 init_server_map(curproxy);
6513 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006514 break;
6515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516
6517 if (curproxy->options & PR_O_LOGASAP)
6518 curproxy->to_log &= ~LW_BYTES;
6519
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006520 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006521 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006522 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6523 proxy_type_str(curproxy), curproxy->id);
6524 err_code |= ERR_WARN;
6525 }
6526
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006527 if (curproxy->mode != PR_MODE_HTTP) {
6528 int optnum;
6529
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006530 if (curproxy->uri_auth) {
6531 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6532 proxy_type_str(curproxy), curproxy->id);
6533 err_code |= ERR_WARN;
6534 curproxy->uri_auth = NULL;
6535 }
6536
Willy Tarreau87cf5142011-08-19 22:57:24 +02006537 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006538 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6539 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6540 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006541 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006542 }
6543
6544 if (curproxy->options & PR_O_ORGTO) {
6545 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6546 "originalto", proxy_type_str(curproxy), curproxy->id);
6547 err_code |= ERR_WARN;
6548 curproxy->options &= ~PR_O_ORGTO;
6549 }
6550
6551 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6552 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6553 (curproxy->cap & cfg_opts[optnum].cap) &&
6554 (curproxy->options & cfg_opts[optnum].val)) {
6555 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6556 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6557 err_code |= ERR_WARN;
6558 curproxy->options &= ~cfg_opts[optnum].val;
6559 }
6560 }
6561
6562 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6563 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6564 (curproxy->cap & cfg_opts2[optnum].cap) &&
6565 (curproxy->options2 & cfg_opts2[optnum].val)) {
6566 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6567 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6568 err_code |= ERR_WARN;
6569 curproxy->options2 &= ~cfg_opts2[optnum].val;
6570 }
6571 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006572
Willy Tarreauefa5f512010-03-30 20:13:29 +02006573#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006574 if (curproxy->bind_hdr_occ) {
6575 curproxy->bind_hdr_occ = 0;
6576 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6577 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6578 err_code |= ERR_WARN;
6579 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006580#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006581 }
6582
Willy Tarreaubaaee002006-06-26 02:48:02 +02006583 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006584 * ensure that we're not cross-dressing a TCP server into HTTP.
6585 */
6586 newsrv = curproxy->srv;
6587 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006588 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006589 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6590 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006591 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006592 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006593
Willy Tarreau0cec3312011-10-31 13:49:26 +01006594 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6595 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6596 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6597 err_code |= ERR_WARN;
6598 }
6599
Willy Tarreauefa5f512010-03-30 20:13:29 +02006600#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006601 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6602 newsrv->bind_hdr_occ = 0;
6603 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6604 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6605 err_code |= ERR_WARN;
6606 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006607#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006608 newsrv = newsrv->next;
6609 }
6610
Willy Tarreauc1a21672009-08-16 22:37:44 +02006611 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006612 curproxy->accept = frontend_accept;
6613
Willy Tarreauc1a21672009-08-16 22:37:44 +02006614 if (curproxy->tcp_req.inspect_delay ||
6615 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006616 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006617
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006618 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006619 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006620 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006621 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006622
6623 /* both TCP and HTTP must check switching rules */
6624 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6625 }
6626
6627 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006628 if (curproxy->tcp_req.inspect_delay ||
6629 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6630 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6631
Emeric Brun97679e72010-09-23 17:56:44 +02006632 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6633 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6634
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006635 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006636 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006637 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006638 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006639
6640 /* If the backend does requires RDP cookie persistence, we have to
6641 * enable the corresponding analyser.
6642 */
6643 if (curproxy->options2 & PR_O2_RDPC_PRST)
6644 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6645 }
6646
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006647 listener = NULL;
6648 while (curproxy->listen) {
6649 struct listener *next;
6650
6651 next = curproxy->listen->next;
6652 curproxy->listen->next = listener;
6653 listener = curproxy->listen;
6654
6655 if (!next)
6656 break;
6657
6658 curproxy->listen = next;
6659 }
6660
Willy Tarreaue6b98942007-10-29 01:09:36 +01006661 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006662 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006663 listener = curproxy->listen;
6664 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006665 if (!listener->luid) {
6666 /* listener ID not set, use automatic numbering with first
6667 * spare entry starting with next_luid.
6668 */
6669 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6670 listener->conf.id.key = listener->luid = next_id;
6671 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006672 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006673 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006674
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006675 /* enable separate counters */
6676 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6677 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6678 if (!listener->name) {
6679 sprintf(trash, "sock-%d", listener->luid);
6680 listener->name = strdup(trash);
6681 }
6682 }
6683
Emeric Brun6e159292012-05-18 16:32:13 +02006684#ifdef USE_OPENSSL
6685#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6686#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6687#endif
6688#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6689#define SSL_OP_NO_COMPRESSION 0
6690#endif
6691#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6692#define SSL_MODE_RELEASE_BUFFERS 0
6693#endif
6694 /* Initialize SSL */
6695 if (listener->ssl_cert) {
6696 int ssloptions =
6697 SSL_OP_ALL | /* all known workarounds for bugs */
6698 SSL_OP_NO_SSLv2 |
6699 SSL_OP_NO_COMPRESSION |
6700 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6701 int sslmode =
6702 SSL_MODE_ENABLE_PARTIAL_WRITE |
6703 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6704 SSL_MODE_RELEASE_BUFFERS;
6705
6706 listener->data = &ssl_sock; /* data layer */
6707 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6708 if (!listener->ssl_ctx.ctx) {
6709 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6710 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6711 cfgerr++;
6712 goto skip_ssl;
6713 }
6714 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6715 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6716 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
Emeric Brunfc32aca2012-09-03 12:10:29 +02006717 if (shared_context_init(global.tune.sslcachesize) < 0) {
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006718 Alert("Unable to allocate SSL session cache.\n");
6719 cfgerr++;
6720 goto skip_ssl;
6721 }
6722 shared_context_set_cache(listener->ssl_ctx.ctx);
6723
Emeric Brune1f38db2012-09-03 20:36:47 +02006724 SSL_CTX_set_info_callback(listener->ssl_ctx.ctx, ssl_sock_infocbk);
Emeric Brun6e159292012-05-18 16:32:13 +02006725
6726 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6727 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6728 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6729 cfgerr++;
6730 goto skip_ssl;
6731 }
6732
6733 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6734 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6735 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6736 cfgerr++;
6737 goto skip_ssl;
6738 }
6739 }
6740 skip_ssl:
6741#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006742 if (curproxy->options & PR_O_TCP_NOLING)
6743 listener->options |= LI_O_NOLINGER;
6744 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006745 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006746 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006747 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006748 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006749 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006750 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006751
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006752 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6753 listener->options |= LI_O_TCP_RULES;
6754
Willy Tarreaude3041d2010-05-31 10:56:17 +02006755 if (curproxy->mon_mask.s_addr)
6756 listener->options |= LI_O_CHK_MONNET;
6757
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006758 /* smart accept mode is automatic in HTTP mode */
6759 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreaufbac6632012-09-03 22:33:40 +02006760 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_cert) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006761 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6762 listener->options |= LI_O_NOQUICKACK;
6763
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006764 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006765 listener = listener->next;
6766 }
6767
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006768 /* Check multi-process mode compatibility for the current proxy */
6769 if (global.nbproc > 1) {
6770 int nbproc = 0;
6771 if (curproxy->bind_proc) {
6772 int proc;
6773 for (proc = 0; proc < global.nbproc; proc++) {
6774 if (curproxy->bind_proc & (1 << proc)) {
6775 nbproc++;
6776 }
6777 }
6778 } else {
6779 nbproc = global.nbproc;
6780 }
6781 if (curproxy->table.peers.name) {
6782 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6783 curproxy->id);
6784 cfgerr++;
6785 }
6786 if (nbproc > 1) {
6787 if (curproxy->uri_auth) {
6788 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6789 curproxy->id);
6790 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6791 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6792 curproxy->id);
6793 }
6794 }
6795 if (curproxy->appsession_name) {
6796 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6797 curproxy->id);
6798 }
6799 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6800 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6801 curproxy->id);
6802 }
6803 }
6804 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006805
6806 /* create the task associated with the proxy */
6807 curproxy->task = task_new();
6808 if (curproxy->task) {
6809 curproxy->task->context = curproxy;
6810 curproxy->task->process = manage_proxy;
6811 /* no need to queue, it will be done automatically if some
6812 * listener gets limited.
6813 */
6814 curproxy->task->expire = TICK_ETERNITY;
6815 } else {
6816 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6817 curproxy->id);
6818 cfgerr++;
6819 }
6820
Willy Tarreaubaaee002006-06-26 02:48:02 +02006821 curproxy = curproxy->next;
6822 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006823
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006824 /* Check multi-process mode compatibility */
6825 if (global.nbproc > 1) {
6826 if (global.stats_fe) {
6827 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6828 }
6829 }
6830
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006831 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6832 struct auth_users *curuser;
6833 int g;
6834
6835 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6836 unsigned int group_mask = 0;
6837 char *group = NULL;
6838
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006839 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006840 continue;
6841
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006842 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006843
6844 for (g = 0; g < curuserlist->grpcnt; g++)
6845 if (!strcmp(curuserlist->groups[g], group))
6846 break;
6847
6848 if (g == curuserlist->grpcnt) {
6849 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6850 curuserlist->name, group, curuser->user);
6851 err_code |= ERR_ALERT | ERR_FATAL;
6852 goto out;
6853 }
6854
6855 group_mask |= (1 << g);
6856 }
6857
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006858 free(curuser->u.groups);
6859 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006860 }
6861
6862 for (g = 0; g < curuserlist->grpcnt; g++) {
6863 char *user = NULL;
6864
6865 if (!curuserlist->groupusers[g])
6866 continue;
6867
6868 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6869 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6870 if (!strcmp(curuser->user, user))
6871 break;
6872
6873 if (!curuser) {
6874 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6875 curuserlist->name, user, curuserlist->groups[g]);
6876 err_code |= ERR_ALERT | ERR_FATAL;
6877 goto out;
6878 }
6879
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006880 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006881 }
6882
6883 free(curuserlist->groupusers[g]);
6884 }
6885
6886 free(curuserlist->groupusers);
6887
6888#ifdef DEBUG_AUTH
6889 for (g = 0; g < curuserlist->grpcnt; g++) {
6890 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6891
6892 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006893 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006894 fprintf(stderr, " %s", curuser->user);
6895 }
6896
6897 fprintf(stderr, "\n");
6898 }
6899#endif
6900
Willy Tarreaufbb78422011-06-05 15:38:35 +02006901 }
6902
6903 /* automatically compute fullconn if not set. We must not do it in the
6904 * loop above because cross-references are not yet fully resolved.
6905 */
6906 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6907 /* If <fullconn> is not set, let's set it to 10% of the sum of
6908 * the possible incoming frontend's maxconns.
6909 */
6910 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6911 struct proxy *fe;
6912 int total = 0;
6913
6914 /* sum up the number of maxconns of frontends which
6915 * reference this backend at least once or which are
6916 * the same one ('listen').
6917 */
6918 for (fe = proxy; fe; fe = fe->next) {
6919 struct switching_rule *rule;
6920 struct hdr_exp *exp;
6921 int found = 0;
6922
6923 if (!(fe->cap & PR_CAP_FE))
6924 continue;
6925
6926 if (fe == curproxy) /* we're on a "listen" instance */
6927 found = 1;
6928
6929 if (fe->defbe.be == curproxy) /* "default_backend" */
6930 found = 1;
6931
6932 /* check if a "use_backend" rule matches */
6933 if (!found) {
6934 list_for_each_entry(rule, &fe->switching_rules, list) {
6935 if (rule->be.backend == curproxy) {
6936 found = 1;
6937 break;
6938 }
6939 }
6940 }
6941
6942 /* check if a "reqsetbe" rule matches */
6943 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6944 if (exp->action == ACT_SETBE &&
6945 (struct proxy *)exp->replace == curproxy) {
6946 found = 1;
6947 break;
6948 }
6949 }
6950
6951 /* now we've checked all possible ways to reference a backend
6952 * from a frontend.
6953 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006954 if (!found)
6955 continue;
6956 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006957 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006958 /* we have the sum of the maxconns in <total>. We only
6959 * keep 10% of that sum to set the default fullconn, with
6960 * a hard minimum of 1 (to avoid a divide by zero).
6961 */
6962 curproxy->fullconn = (total + 9) / 10;
6963 if (!curproxy->fullconn)
6964 curproxy->fullconn = 1;
6965 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006966 }
6967
Willy Tarreau056f5682010-06-06 15:51:11 +02006968 /* initialize stick-tables on backend capable proxies. This must not
6969 * be done earlier because the data size may be discovered while parsing
6970 * other proxies.
6971 */
6972 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006973 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006974
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006975 /*
6976 * Recount currently required checks.
6977 */
6978
6979 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6980 int optnum;
6981
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006982 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6983 if (curproxy->options & cfg_opts[optnum].val)
6984 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006985
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006986 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6987 if (curproxy->options2 & cfg_opts2[optnum].val)
6988 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006989 }
6990
Willy Tarreau122541c2011-09-07 21:24:49 +02006991 if (peers) {
6992 struct peers *curpeers = peers, **last;
6993 struct peer *p, *pb;
6994
6995 /* Remove all peers sections which don't have a valid listener.
6996 * This can happen when a peers section is never referenced and
6997 * does not contain a local peer.
6998 */
6999 last = &peers;
7000 while (*last) {
7001 curpeers = *last;
7002 if (curpeers->peers_fe) {
7003 last = &curpeers->next;
7004 continue;
7005 }
7006
7007 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7008 curpeers->id, localpeer);
7009
7010 p = curpeers->remote;
7011 while (p) {
7012 pb = p->next;
7013 free(p->id);
7014 free(p);
7015 p = pb;
7016 }
7017
7018 /* Destroy and unlink this curpeers section.
7019 * Note: curpeers is backed up into *last.
7020 */
7021 free(curpeers->id);
7022 curpeers = curpeers->next;
7023 free(*last);
7024 *last = curpeers;
7025 }
7026 }
7027
Willy Tarreauac1932d2011-10-24 19:14:41 +02007028 if (!global.tune.max_http_hdr)
7029 global.tune.max_http_hdr = MAX_HTTP_HDR;
7030
Willy Tarreau34eb6712011-10-24 18:15:04 +02007031 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007032 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007033 MEM_F_SHARED);
7034
Willy Tarreaubb925012009-07-23 13:36:36 +02007035 if (cfgerr > 0)
7036 err_code |= ERR_ALERT | ERR_FATAL;
7037 out:
7038 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039}
7040
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007041/*
7042 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7043 * parsing sessions.
7044 */
7045void cfg_register_keywords(struct cfg_kw_list *kwl)
7046{
7047 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7048}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007050/*
7051 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7052 */
7053void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7054{
7055 LIST_DEL(&kwl->list);
7056 LIST_INIT(&kwl->list);
7057}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007058
7059/*
7060 * Local variables:
7061 * c-indent-level: 8
7062 * c-basic-offset: 8
7063 * End:
7064 */