blob: 27bed6ce543e10b17046a9826a5816a5cfd4a779 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Emeric Brunaa35f1f2012-09-03 11:53:36 +020065#include <proto/shctx.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020067#ifdef USE_OPENSSL
68#include <proto/ssl_sock.h>
69#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020070#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010071#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072
73
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100195static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196{
197 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100198 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 int port, end;
200
201 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 while (next && *next) {
204 struct sockaddr_storage ss;
205
206 str = next;
207 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100208 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 *next++ = 0;
210 }
211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (*str == '/') {
213 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
214 /* so compute max path */
215 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
216 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Emeric Bruned760922010-10-22 17:59:25 +0200218 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100219 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
220 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200221 goto fail;
222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200225 ss.ss_family = AF_UNIX;
226 if (global.unix_bind.prefix) {
227 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
228 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
Emeric Bruned760922010-10-22 17:59:25 +0200230 else {
231 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
232 }
233 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 }
235 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 ss2 = str2sa_range(str, &port, &end);
239 if (!ss2) {
240 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
246 Alert("parsing [%s:%d] : missing port number: '%s'\n",
247 file, line, str);
248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 /* OK the address looks correct */
252 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
262 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 l->next = curproxy->listen;
270 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
272 l->fd = -1;
273 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200274 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 l->state = LI_INIT;
276
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100277 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100279 tcpv4_add_listener(l);
280 }
Emeric Bruned760922010-10-22 17:59:25 +0200281 else if (ss.ss_family == AF_INET6) {
282 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
283 tcpv6_add_listener(l);
284 }
285 else {
286 l->perm.ux.gid = l->perm.ux.uid = -1;
287 l->perm.ux.mode = 0;
288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
471 else if (!strcmp(args[0], "daemon")) {
472 global.mode |= MODE_DAEMON;
473 }
474 else if (!strcmp(args[0], "debug")) {
475 global.mode |= MODE_DEBUG;
476 }
477 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
483 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100489 else if (!strcmp(args[0], "nosplice")) {
490 global.tune.options &= ~GTUNE_USE_SPLICE;
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 else if (!strcmp(args[0], "quiet")) {
493 global.mode |= MODE_QUIET;
494 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 else if (!strcmp(args[0], "tune.maxpollevents")) {
496 if (global.tune.maxpollevents != 0) {
497 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 if (*(args[1]) == 0) {
502 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT | ERR_FATAL;
504 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200505 }
506 global.tune.maxpollevents = atol(args[1]);
507 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 else if (!strcmp(args[0], "tune.maxaccept")) {
509 if (global.tune.maxaccept != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100518 }
519 global.tune.maxaccept = atol(args[1]);
520 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200521 else if (!strcmp(args[0], "tune.chksize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.chksize = atol(args[1]);
528 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200529#ifdef USE_OPENSSL
530 else if (!strcmp(args[0], "tune.sslcachesize")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.sslcachesize = atol(args[1]);
537 }
538#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 else if (!strcmp(args[0], "tune.bufsize")) {
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.tune.bufsize = atol(args[1]);
546 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
547 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200548 trashlen = global.tune.bufsize;
549 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 }
551 else if (!strcmp(args[0], "tune.maxrewrite")) {
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.maxrewrite = atol(args[1]);
558 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
559 global.tune.maxrewrite = global.tune.bufsize / 2;
560 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100561 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
562 if (global.tune.client_rcvbuf != 0) {
563 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT;
565 goto out;
566 }
567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.client_rcvbuf = atol(args[1]);
573 }
574 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
575 if (global.tune.server_rcvbuf != 0) {
576 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.tune.server_rcvbuf = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "tune.sndbuf.client")) {
588 if (global.tune.client_sndbuf != 0) {
589 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT;
591 goto out;
592 }
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.client_sndbuf = atol(args[1]);
599 }
600 else if (!strcmp(args[0], "tune.sndbuf.server")) {
601 if (global.tune.server_sndbuf != 0) {
602 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT;
604 goto out;
605 }
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.server_sndbuf = atol(args[1]);
612 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200613 else if (!strcmp(args[0], "tune.pipesize")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.pipesize = atol(args[1]);
620 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200621 else if (!strcmp(args[0], "tune.http.maxhdr")) {
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.max_http_hdr = atol(args[1]);
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "uid")) {
630 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.uid = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "gid")) {
643 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.gid = atol(args[1]);
654 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 /* user/group name handling */
656 else if (!strcmp(args[0], "user")) {
657 struct passwd *ha_user;
658 if (global.uid != 0) {
659 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_user = getpwnam(args[1]);
665 if (ha_user != NULL) {
666 global.uid = (int)ha_user->pw_uid;
667 }
668 else {
669 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 else if (!strcmp(args[0], "group")) {
674 struct group *ha_group;
675 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200676 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 }
680 errno = 0;
681 ha_group = getgrnam(args[1]);
682 if (ha_group != NULL) {
683 global.gid = (int)ha_group->gr_gid;
684 }
685 else {
686 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200688 }
689 }
690 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 else if (!strcmp(args[0], "nbproc")) {
692 if (global.nbproc != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.nbproc = atol(args[1]);
703 }
704 else if (!strcmp(args[0], "maxconn")) {
705 if (global.maxconn != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 global.maxconn = atol(args[1]);
716#ifdef SYSTEM_MAXCONN
717 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
718 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
719 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722#endif /* SYSTEM_MAXCONN */
723 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200724 else if (!strcmp(args[0], "maxsslconn")) {
725#ifdef USE_OPENSSL
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.maxsslconn = atol(args[1]);
732#else
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#endif
739 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200740 else if (!strcmp(args[0], "maxconnrate")) {
741 if (global.cps_lim != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
743 err_code |= ERR_ALERT;
744 goto out;
745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.cps_lim = atol(args[1]);
752 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100753 else if (!strcmp(args[0], "maxpipes")) {
754 if (global.maxpipes != 0) {
755 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100763 }
764 global.maxpipes = atol(args[1]);
765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 else if (!strcmp(args[0], "ulimit-n")) {
767 if (global.rlimit_nofile != 0) {
768 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 if (*(args[1]) == 0) {
773 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 global.rlimit_nofile = atol(args[1]);
778 }
779 else if (!strcmp(args[0], "chroot")) {
780 if (global.chroot != NULL) {
781 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 if (*(args[1]) == 0) {
786 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT | ERR_FATAL;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 global.chroot = strdup(args[1]);
791 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200792 else if (!strcmp(args[0], "description")) {
793 int i, len=0;
794 char *d;
795
796 if (!*args[1]) {
797 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802
803 for(i=1; *args[i]; i++)
804 len += strlen(args[i])+1;
805
806 if (global.desc)
807 free(global.desc);
808
809 global.desc = d = (char *)calloc(1, len);
810
811 d += sprintf(d, "%s", args[1]);
812 for(i=2; *args[i]; i++)
813 d += sprintf(d, " %s", args[i]);
814 }
815 else if (!strcmp(args[0], "node")) {
816 int i;
817 char c;
818
819 for (i=0; args[1][i]; i++) {
820 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100821 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
822 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200823 break;
824 }
825
826 if (!i || args[1][i]) {
827 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
828 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833
834 if (global.node)
835 free(global.node);
836
837 global.node = strdup(args[1]);
838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 else if (!strcmp(args[0], "pidfile")) {
840 if (global.pidfile != NULL) {
841 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.pidfile = strdup(args[1]);
851 }
Emeric Bruned760922010-10-22 17:59:25 +0200852 else if (!strcmp(args[0], "unix-bind")) {
853 int cur_arg = 1;
854 while (*(args[cur_arg])) {
855 if (!strcmp(args[cur_arg], "prefix")) {
856 if (global.unix_bind.prefix != NULL) {
857 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
858 err_code |= ERR_ALERT;
859 cur_arg += 2;
860 continue;
861 }
862
863 if (*(args[cur_arg+1]) == 0) {
864 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868 global.unix_bind.prefix = strdup(args[cur_arg+1]);
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "mode")) {
874
875 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
876 cur_arg += 2;
877 continue;
878 }
879
880 if (!strcmp(args[cur_arg], "uid")) {
881
882 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
883 cur_arg += 2;
884 continue;
885 }
886
887 if (!strcmp(args[cur_arg], "gid")) {
888
889 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "user")) {
895 struct passwd *user;
896
897 user = getpwnam(args[cur_arg + 1]);
898 if (!user) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
900 file, linenum, args[0], args[cur_arg + 1 ]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 global.unix_bind.ux.uid = user->pw_uid;
906 cur_arg += 2;
907 continue;
908 }
909
910 if (!strcmp(args[cur_arg], "group")) {
911 struct group *group;
912
913 group = getgrnam(args[cur_arg + 1]);
914 if (!group) {
915 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
916 file, linenum, args[0], args[cur_arg + 1 ]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920
921 global.unix_bind.ux.gid = group->gr_gid;
922 cur_arg += 2;
923 continue;
924 }
925
Willy Tarreaub48f9582011-09-05 01:17:06 +0200926 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200927 file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
William Lallemand0f99e342011-10-12 17:50:54 +0200932 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
933 /* delete previous herited or defined syslog servers */
934 struct logsrv *back;
935 struct logsrv *tmp;
936
937 if (*(args[1]) != 0) {
938 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942
943 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
944 LIST_DEL(&tmp->list);
945 free(tmp);
946 }
947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200949 struct logsrv *logsrv;
950
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[1]) == 0 || *(args[2]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
William Lallemand0f99e342011-10-12 17:50:54 +0200956
957 logsrv = calloc(1, sizeof(struct logsrv));
958
959 logsrv->facility = get_log_facility(args[2]);
960 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->level = get_log_level(args[3]);
969 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 }
975
William Lallemand0f99e342011-10-12 17:50:54 +0200976 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200978 logsrv->minlvl = get_log_level(args[4]);
979 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200982 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200983 }
984 }
985
Robert Tsai81ae1952007-12-05 10:47:29 +0100986 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 if (!sk) {
989 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100990 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100991 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200992 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100993 goto out;
994 }
William Lallemand0f99e342011-10-12 17:50:54 +0200995 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100996 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100997 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100998 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1000 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001001 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001002 goto out;
1003 }
William Lallemand0f99e342011-10-12 17:50:54 +02001004 logsrv->addr = *sk;
1005 if (!get_host_port(&logsrv->addr))
1006 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008
William Lallemand0f99e342011-10-12 17:50:54 +02001009 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001011 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1012 char *name;
1013 int len;
1014
1015 if (global.log_send_hostname != NULL) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT;
1018 goto out;
1019 }
1020
1021 if (*(args[1]))
1022 name = args[1];
1023 else
1024 name = hostname;
1025
1026 len = strlen(name);
1027
1028 /* We'll add a space after the name to respect the log format */
1029 free(global.log_send_hostname);
1030 global.log_send_hostname = malloc(len + 2);
1031 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1032 }
Kevinm48936af2010-12-22 16:08:21 +00001033 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1034 if (*(args[1]) == 0) {
1035 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 free(global.log_tag);
1040 global.log_tag = strdup(args[1]);
1041 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001042 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1043 if (global.spread_checks != 0) {
1044 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT;
1046 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001047 }
1048 if (*(args[1]) == 0) {
1049 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
1051 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001052 }
1053 global.spread_checks = atol(args[1]);
1054 if (global.spread_checks < 0 || global.spread_checks > 50) {
1055 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 struct cfg_kw_list *kwl;
1061 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001062 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001063
1064 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1065 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1066 if (kwl->kw[index].section != CFG_GLOBAL)
1067 continue;
1068 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1069 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001070 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001071 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001072 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001073 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001074 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001076 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001077 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001078 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_WARN;
1080 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001081 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001082 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001083 }
1084 }
1085 }
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001090
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001092 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094}
1095
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001096void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001098 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 defproxy.mode = PR_MODE_TCP;
1100 defproxy.state = PR_STNEW;
1101 defproxy.maxconn = cfg_maxpconn;
1102 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001103
1104 defproxy.defsrv.inter = DEF_CHKINTR;
1105 defproxy.defsrv.fastinter = 0;
1106 defproxy.defsrv.downinter = 0;
1107 defproxy.defsrv.rise = DEF_RISETIME;
1108 defproxy.defsrv.fall = DEF_FALLTIME;
1109 defproxy.defsrv.check_port = 0;
1110 defproxy.defsrv.maxqueue = 0;
1111 defproxy.defsrv.minconn = 0;
1112 defproxy.defsrv.maxconn = 0;
1113 defproxy.defsrv.slowstart = 0;
1114 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1115 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1116 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001117}
1118
Willy Tarreauade5ec42010-01-28 19:33:49 +01001119
1120static int create_cond_regex_rule(const char *file, int line,
1121 struct proxy *px, int dir, int action, int flags,
1122 const char *cmd, const char *reg, const char *repl,
1123 const char **cond_start)
1124{
1125 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001126 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 const char *err;
1128 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001129 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130
1131 if (px == &defproxy) {
1132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (*reg == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1144 err_code |= ERR_WARN;
1145
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 if (cond_start &&
1147 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001148 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1149 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1150 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto err;
1153 }
1154 }
1155 else if (cond_start && **cond_start) {
1156 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1157 file, line, cmd, *cond_start);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001163 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001164 else
1165 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001166
Willy Tarreauade5ec42010-01-28 19:33:49 +01001167 preg = calloc(1, sizeof(regex_t));
1168 if (!preg) {
1169 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1170 err_code = ERR_ALERT | ERR_FATAL;
1171 goto err;
1172 }
1173
1174 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1175 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1176 err_code = ERR_ALERT | ERR_FATAL;
1177 goto err;
1178 }
1179
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001180 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001181 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001182 if (repl && err) {
1183 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1184 file, line, cmd, *err);
1185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto err;
1187 }
1188
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001189 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 err_code |= ERR_WARN;
1191
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 return err_code;
1194 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001195 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001196 free(preg);
1197 return err_code;
1198}
1199
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001201 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001202 * Returns the error code, 0 if OK, or any combination of :
1203 * - ERR_ABORT: must abort ASAP
1204 * - ERR_FATAL: we can continue parsing but not start the service
1205 * - ERR_WARN: a warning has been emitted
1206 * - ERR_ALERT: an alert has been emitted
1207 * Only the two first ones can stop processing, the two others are just
1208 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001209 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001210int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1211{
1212 static struct peers *curpeers = NULL;
1213 struct peer *newpeer = NULL;
1214 const char *err;
1215 int err_code = 0;
1216
1217 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1218
1219 err = invalid_char(args[1]);
1220 if (err) {
1221 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1222 file, linenum, *err, args[0], args[1]);
1223 err_code |= ERR_ALERT | ERR_FATAL;
1224 }
1225
1226 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1227 /*
1228 * If there are two proxies with the same name only following
1229 * combinations are allowed:
1230 */
1231 if (strcmp(curpeers->id, args[1]) == 0) {
1232 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1233 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1234 err_code |= ERR_WARN;
1235 }
1236 }
1237
1238 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1239 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1240 err_code |= ERR_ALERT | ERR_ABORT;
1241 goto out;
1242 }
1243
1244 curpeers->next = peers;
1245 peers = curpeers;
1246 curpeers->conf.file = file;
1247 curpeers->conf.line = linenum;
1248 curpeers->last_change = now.tv_sec;
1249 curpeers->id = strdup(args[1]);
1250 }
1251 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1252 char *rport, *raddr;
1253 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001254 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (!*args[2]) {
1257 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1258 file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 err = invalid_char(args[1]);
1264 if (err) {
1265 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1266 file, linenum, *err, args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 /* the peers are linked backwards first */
1278 curpeers->count++;
1279 newpeer->next = curpeers->remote;
1280 curpeers->remote = newpeer;
1281 newpeer->peers = curpeers;
1282 newpeer->conf.file = file;
1283 newpeer->conf.line = linenum;
1284
1285 newpeer->last_change = now.tv_sec;
1286 newpeer->id = strdup(args[1]);
1287
1288 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001289 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 if (rport) {
1291 *rport++ = 0;
1292 realport = atol(rport);
1293 }
1294 if (!realport) {
1295 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
Willy Tarreaufab5a432011-03-04 15:31:53 +01001300 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 free(raddr);
1302 if (!sk) {
1303 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001308 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001309 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
1312 if (!sk) {
1313 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1314 file, linenum, newpeer->addr.ss_family, args[2]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001319 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320
1321 if (strcmp(newpeer->id, localpeer) == 0) {
1322 /* Current is local peer, it define a frontend */
1323 newpeer->local = 1;
1324
1325 if (!curpeers->peers_fe) {
1326 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 err_code |= ERR_ALERT | ERR_ABORT;
1329 goto out;
1330 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001331
Willy Tarreau237250c2011-07-29 01:49:03 +02001332 init_new_proxy(curpeers->peers_fe);
1333 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001334
1335 curpeers->peers_fe->last_change = now.tv_sec;
1336 curpeers->peers_fe->id = strdup(args[1]);
1337 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001338 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1340 curpeers->peers_fe->timeout.connect = 5000;
1341 curpeers->peers_fe->accept = peer_accept;
1342 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001343 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001344 err_code |= ERR_FATAL;
1345 goto out;
1346 }
1347 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1348 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1349 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1350 curpeers->peers_fe->listen->accept = session_accept;
1351 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1352 curpeers->peers_fe->listen->handler = process_session;
1353 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001354 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1355 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001356 }
1357 }
1358 } /* neither "peer" nor "peers" */
1359 else if (*args[0] != 0) {
1360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1361 err_code |= ERR_ALERT | ERR_FATAL;
1362 goto out;
1363 }
1364
1365out:
1366 return err_code;
1367}
1368
1369
Willy Tarreau3842f002009-06-14 11:39:52 +02001370int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371{
1372 static struct proxy *curproxy = NULL;
1373 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001374 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001375 int rc;
1376 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001377 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001378 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001379 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001380 char *errmsg = NULL;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001381 struct ssl_conf *ssl_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382
Willy Tarreau977b8e42006-12-29 14:19:17 +01001383 if (!strcmp(args[0], "listen"))
1384 rc = PR_CAP_LISTEN;
1385 else if (!strcmp(args[0], "frontend"))
1386 rc = PR_CAP_FE | PR_CAP_RS;
1387 else if (!strcmp(args[0], "backend"))
1388 rc = PR_CAP_BE | PR_CAP_RS;
1389 else if (!strcmp(args[0], "ruleset"))
1390 rc = PR_CAP_RS;
1391 else
1392 rc = PR_CAP_NONE;
1393
1394 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395 if (!*args[1]) {
1396 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1397 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1398 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001399 err_code |= ERR_ALERT | ERR_ABORT;
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001402
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001403 err = invalid_char(args[1]);
1404 if (err) {
1405 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1406 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001407 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001408 }
1409
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001410 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1411 /*
1412 * If there are two proxies with the same name only following
1413 * combinations are allowed:
1414 *
1415 * listen backend frontend ruleset
1416 * listen - - - -
1417 * backend - - OK -
1418 * frontend - OK - -
1419 * ruleset - - - -
1420 */
1421
1422 if (!strcmp(curproxy->id, args[1]) &&
1423 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1424 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001425 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1426 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1427 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001428 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001429 }
1430 }
1431
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_ALERT | ERR_ABORT;
1435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001437
Willy Tarreau97cb7802010-01-03 20:23:58 +01001438 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 curproxy->next = proxy;
1440 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001441 curproxy->conf.file = file;
1442 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001443 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446
1447 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001449 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001450 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001451 err_code |= ERR_FATAL;
1452 goto out;
1453 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001454 new = curproxy->listen;
1455 while (new != last) {
1456 new->conf.file = file;
1457 new->conf.line = linenum;
1458 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001459 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 }
1462
1463 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001464 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001465 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001466
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001469 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001470 curproxy->no_options = defproxy.no_options;
1471 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001472 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001473 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001474 curproxy->except_net = defproxy.except_net;
1475 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001476 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001477 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001479 if (defproxy.fwdfor_hdr_len) {
1480 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1481 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1482 }
1483
Willy Tarreaub86db342009-11-30 11:50:16 +01001484 if (defproxy.orgto_hdr_len) {
1485 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1486 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1487 }
1488
Mark Lamourinec2247f02012-01-04 13:02:01 -05001489 if (defproxy.server_id_hdr_len) {
1490 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1491 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1492 }
1493
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (curproxy->cap & PR_CAP_FE) {
1495 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001496 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001497 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498
1499 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001500 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1501 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502
1503 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505
Willy Tarreau977b8e42006-12-29 14:19:17 +01001506 if (curproxy->cap & PR_CAP_BE) {
1507 curproxy->fullconn = defproxy.fullconn;
1508 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001510 if (defproxy.check_req) {
1511 curproxy->check_req = calloc(1, defproxy.check_len);
1512 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1513 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001516 if (defproxy.expect_str) {
1517 curproxy->expect_str = strdup(defproxy.expect_str);
1518 if (defproxy.expect_regex) {
1519 /* note: this regex is known to be valid */
1520 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1521 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1522 }
1523 }
1524
Willy Tarreau67402132012-05-31 20:40:20 +02001525 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 if (defproxy.cookie_name)
1527 curproxy->cookie_name = strdup(defproxy.cookie_name);
1528 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001529 if (defproxy.cookie_domain)
1530 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001531
Willy Tarreau31936852010-10-06 16:59:56 +02001532 if (defproxy.cookie_maxidle)
1533 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1534
1535 if (defproxy.cookie_maxlife)
1536 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1537
Emeric Brun647caf12009-06-30 17:57:00 +02001538 if (defproxy.rdp_cookie_name)
1539 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1540 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1541
Willy Tarreau01732802007-11-01 22:48:15 +01001542 if (defproxy.url_param_name)
1543 curproxy->url_param_name = strdup(defproxy.url_param_name);
1544 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001545
Benoitaffb4812009-03-25 13:02:10 +01001546 if (defproxy.hh_name)
1547 curproxy->hh_name = strdup(defproxy.hh_name);
1548 curproxy->hh_len = defproxy.hh_len;
1549 curproxy->hh_match_domain = defproxy.hh_match_domain;
1550
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001551 if (defproxy.iface_name)
1552 curproxy->iface_name = strdup(defproxy.iface_name);
1553 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001554 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001556 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557 if (defproxy.capture_name)
1558 curproxy->capture_name = strdup(defproxy.capture_name);
1559 curproxy->capture_namelen = defproxy.capture_namelen;
1560 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562
Willy Tarreau977b8e42006-12-29 14:19:17 +01001563 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001564 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001565 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001566 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001567 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 curproxy->uri_auth = defproxy.uri_auth;
1569 curproxy->mon_net = defproxy.mon_net;
1570 curproxy->mon_mask = defproxy.mon_mask;
1571 if (defproxy.monitor_uri)
1572 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1573 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001574 if (defproxy.defbe.name)
1575 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001576
1577 /* get either a pointer to the logformat string or a copy of it */
1578 curproxy->logformat_string = defproxy.logformat_string;
1579 if (curproxy->logformat_string &&
1580 curproxy->logformat_string != default_http_log_format &&
1581 curproxy->logformat_string != default_tcp_log_format &&
1582 curproxy->logformat_string != clf_http_log_format)
1583 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001584 }
1585
1586 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001587 curproxy->timeout.connect = defproxy.timeout.connect;
1588 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001589 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001590 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001591 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001592 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001593 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001594 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001595 curproxy->source_addr = defproxy.source_addr;
1596 }
1597
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001599
1600 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001601 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001602 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001603 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001604 LIST_INIT(&node->list);
1605 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1606 }
1607
Willy Tarreau196729e2012-05-31 19:30:26 +02001608 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1609 if (curproxy->uniqueid_format_string)
1610 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001611
1612 /* copy default header unique id */
1613 if (defproxy.header_unique_id)
1614 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1615
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001617 curproxy->conf.used_listener_id = EB_ROOT;
1618 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001619
Willy Tarreau93893792009-07-23 13:19:11 +02001620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 }
1622 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1623 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001624 /* FIXME-20070101: we should do this too at the end of the
1625 * config parsing to free all default values.
1626 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001627 free(defproxy.check_req);
1628 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001629 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001630 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001631 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001632 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001633 free(defproxy.capture_name);
1634 free(defproxy.monitor_uri);
1635 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001636 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001637 free(defproxy.fwdfor_hdr_name);
1638 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001639 free(defproxy.orgto_hdr_name);
1640 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001641 free(defproxy.server_id_hdr_name);
1642 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001643 free(defproxy.expect_str);
1644 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001645
Willy Tarreau39b06652012-06-01 10:58:06 +02001646 if (defproxy.logformat_string != default_http_log_format &&
1647 defproxy.logformat_string != default_tcp_log_format &&
1648 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001649 free(defproxy.logformat_string);
1650
1651 free(defproxy.uniqueid_format_string);
1652
Willy Tarreaua534fea2008-08-03 12:19:50 +02001653 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001654 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001655
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 /* we cannot free uri_auth because it might already be used */
1657 init_default_instance();
1658 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001659 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 }
1662 else if (curproxy == NULL) {
1663 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001666 }
1667
Willy Tarreau977b8e42006-12-29 14:19:17 +01001668
1669 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001671 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001672 int cur_arg;
1673
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 if (curproxy == &defproxy) {
1675 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001676 err_code |= ERR_ALERT | ERR_FATAL;
1677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001679 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001680 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681
Emeric Bruned760922010-10-22 17:59:25 +02001682 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001683 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001688
1689 last_listen = curproxy->listen;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001690 ssl_conf = NULL;
Willy Tarreau8a956912010-10-15 14:27:08 +02001691
1692 /* NOTE: the following line might create several listeners if there
1693 * are comma-separated IPs or port ranges. So all further processing
1694 * will have to be applied to all listeners created after last_listen.
1695 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001696 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001700
Willy Tarreau90a570f2009-10-04 20:54:54 +02001701 new_listen = curproxy->listen;
1702 while (new_listen != last_listen) {
1703 new_listen->conf.file = file;
1704 new_listen->conf.line = linenum;
1705 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001706 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001707 }
1708
Emeric Bruned760922010-10-22 17:59:25 +02001709 /* Set default global rights and owner for unix bind */
1710 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1711 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1712 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713 cur_arg = 2;
1714 while (*(args[cur_arg])) {
1715 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1716#ifdef SO_BINDTODEVICE
1717 struct listener *l;
1718
Emeric Bruned760922010-10-22 17:59:25 +02001719 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1720 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1721 file, linenum, args[0], args[cur_arg]);
1722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
1724 }
1725
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001726 if (!*args[cur_arg + 1]) {
1727 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001731 }
1732
1733 for (l = curproxy->listen; l != last_listen; l = l->next)
1734 l->interface = strdup(args[cur_arg + 1]);
1735
1736 global.last_checks |= LSTCHK_NETADM;
1737
1738 cur_arg += 2;
1739 continue;
1740#else
1741 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1742 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001745#endif
1746 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001747 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1748#ifdef TCP_MAXSEG
1749 struct listener *l;
1750 int mss;
1751
Emeric Bruned760922010-10-22 17:59:25 +02001752 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1753 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1754 file, linenum, args[0], args[cur_arg]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
Willy Tarreaube1b9182009-06-14 18:48:19 +02001759 if (!*args[cur_arg + 1]) {
1760 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001764 }
1765
Willy Tarreau48a7e722010-12-24 15:26:39 +01001766 mss = atoi(args[cur_arg + 1]);
1767 if (!mss || abs(mss) > 65535) {
1768 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001769 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001772 }
1773
1774 for (l = curproxy->listen; l != last_listen; l = l->next)
1775 l->maxseg = mss;
1776
1777 cur_arg += 2;
1778 continue;
1779#else
1780 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1781 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001784#endif
1785 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001786
1787 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1788#ifdef TCP_DEFER_ACCEPT
1789 struct listener *l;
1790
1791 for (l = curproxy->listen; l != last_listen; l = l->next)
1792 l->options |= LI_O_DEF_ACCEPT;
1793
1794 cur_arg ++;
1795 continue;
1796#else
1797 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1798 file, linenum, args[0], args[cur_arg]);
1799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801#endif
1802 }
1803
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001804 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001805#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001806 struct listener *l;
1807
Emeric Bruned760922010-10-22 17:59:25 +02001808 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1809 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1810 file, linenum, args[0], args[cur_arg]);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
1814
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001815 for (l = curproxy->listen; l != last_listen; l = l->next)
1816 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001817
1818 cur_arg ++;
1819 continue;
1820#else
1821 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1822 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001825#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001826 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001827
Willy Tarreau32368ce2012-09-06 11:10:55 +02001828 if (!strcmp(args[cur_arg], "maxconn")) {
1829 struct listener *l;
1830 int val;
1831
1832 if (!*args[cur_arg + 1]) {
1833 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1834 file, linenum, args[0]);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839 val = atol(args[cur_arg + 1]);
1840 if (val <= 0) {
1841 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1842 file, linenum, args[0], val);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
1846
1847 for (l = curproxy->listen; l != last_listen; l = l->next)
1848 l->maxconn = val;
1849
1850 cur_arg += 2;
1851 continue;
1852 }
1853
1854 if (!strcmp(args[cur_arg], "backlog")) {
1855 struct listener *l;
1856 int val;
1857
1858 if (!*args[cur_arg + 1]) {
1859 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1860 file, linenum, args[0]);
1861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
1863 }
1864
1865 val = atol(args[cur_arg + 1]);
1866 if (val <= 0) {
1867 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1868 file, linenum, args[0], val);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872
1873 for (l = curproxy->listen; l != last_listen; l = l->next)
1874 l->backlog = val;
1875
1876 cur_arg += 2;
1877 continue;
1878 }
1879
Willy Tarreau50acaaa2012-09-06 14:26:36 +02001880 if (!strcmp(args[cur_arg], "nice")) {
1881 struct listener *l;
1882 int val;
1883
1884 if (!*args[cur_arg + 1]) {
1885 Alert("parsing [%s:%d] : '%s' : missing nice value.\n",
1886 file, linenum, args[0]);
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890
1891 val = atol(args[cur_arg + 1]);
1892 if (val < -1024 || val > 1024) {
1893 Alert("parsing [%s:%d] : '%s' : invalid nice value %d, allowed range is -1024..1024.\n",
1894 file, linenum, args[0], val);
1895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
1897 }
1898
1899 for (l = curproxy->listen; l != last_listen; l = l->next)
1900 l->nice = val;
1901
1902 cur_arg += 2;
1903 continue;
1904 }
1905
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001906 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl */
Emeric Brun6e159292012-05-18 16:32:13 +02001907#ifdef USE_OPENSSL
1908 struct listener *l;
1909
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001910 if (!ssl_conf)
1911 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1912 ssl_conf->cert = strdup(args[cur_arg + 1]);
Emeric Brun6e159292012-05-18 16:32:13 +02001913
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001914 for (l = curproxy->listen; l != last_listen; l = l->next) {
1915 if (!l->ssl_conf) {
1916 l->ssl_conf = ssl_conf;
1917 ssl_conf->ref_cnt++;
1918 }
1919 }
Emeric Brun6e159292012-05-18 16:32:13 +02001920
1921 cur_arg += 2;
1922 continue;
1923#else
1924 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1925 file, linenum, args[0], args[cur_arg]);
1926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
1928#endif
1929 }
1930
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001931 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1932#ifdef USE_OPENSSL
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001933 if (!*args[cur_arg + 1]) {
1934 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1935 file, linenum, args[0]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001940 if (!ssl_conf)
1941 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1942 ssl_conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001943
1944 cur_arg += 2;
1945 continue;
1946#else
1947 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1948 file, linenum, args[0], args[cur_arg]);
1949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
1951#endif
1952 }
1953
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001954 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1955#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001956 if (!ssl_conf)
1957 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1958 ssl_conf->nosslv3 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001959
1960 cur_arg += 1;
1961 continue;
1962#else
1963 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1964 file, linenum, args[0], args[cur_arg]);
1965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
1967#endif
1968 }
1969
1970 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1971#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001972 if (!ssl_conf)
1973 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1974 ssl_conf->notlsv1 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001975
1976 cur_arg += 1;
1977 continue;
1978#else
1979 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1980 file, linenum, args[0], args[cur_arg]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983#endif
1984 }
1985
David BERARDe566ecb2012-09-04 15:15:13 +02001986 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1987#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001988 if (!ssl_conf)
1989 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1990 ssl_conf->prefer_server_ciphers = 1;
David BERARDe566ecb2012-09-04 15:15:13 +02001991
1992 cur_arg += 1;
1993 continue;
1994#else
1995 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1996 file, linenum, args[0], args[cur_arg]);
1997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999#endif
2000 }
2001
Willy Tarreau8a956912010-10-15 14:27:08 +02002002 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
2003 struct listener *l;
2004
2005 for (l = curproxy->listen; l != last_listen; l = l->next)
2006 l->options |= LI_O_ACC_PROXY;
2007
2008 cur_arg ++;
2009 continue;
2010 }
2011
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002012 if (!strcmp(args[cur_arg], "name")) {
2013 struct listener *l;
2014
2015 for (l = curproxy->listen; l != last_listen; l = l->next)
2016 l->name = strdup(args[cur_arg + 1]);
2017
2018 cur_arg += 2;
2019 continue;
2020 }
2021
2022 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002023 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002024 struct listener *l;
2025
2026 if (curproxy->listen->next != last_listen) {
2027 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
2028 file, linenum, args[cur_arg]);
2029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
2031 }
2032
2033 if (!*args[cur_arg + 1]) {
2034 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2035 file, linenum, args[cur_arg]);
2036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
2038 }
2039
2040 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002041 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002042
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002043 if (curproxy->listen->luid <= 0) {
2044 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002045 file, linenum);
2046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
2048 }
2049
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002050 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
2051 if (node) {
2052 l = container_of(node, struct listener, conf.id);
2053 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
2054 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
2059
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002060 cur_arg += 2;
2061 continue;
2062 }
2063
Emeric Bruned760922010-10-22 17:59:25 +02002064 if (!strcmp(args[cur_arg], "mode")) {
2065
2066 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2067 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2068 file, linenum, args[0], args[cur_arg]);
2069 err_code |= ERR_ALERT | ERR_FATAL;
2070 goto out;
2071 }
2072
2073 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
2074
2075 cur_arg += 2;
2076 continue;
2077 }
2078
2079 if (!strcmp(args[cur_arg], "uid")) {
2080
2081 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2082 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2083 file, linenum, args[0], args[cur_arg]);
2084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
2086 }
2087
2088 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
2089 cur_arg += 2;
2090 continue;
2091 }
2092
2093 if (!strcmp(args[cur_arg], "gid")) {
2094
2095 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2096 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2097 file, linenum, args[0], args[cur_arg]);
2098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
2100 }
2101
2102 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2103 cur_arg += 2;
2104 continue;
2105 }
2106
2107 if (!strcmp(args[cur_arg], "user")) {
2108 struct passwd *user;
2109
2110 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2111 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2112 file, linenum, args[0], args[cur_arg]);
2113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
2115 }
2116 user = getpwnam(args[cur_arg + 1]);
2117 if (!user) {
2118 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2119 file, linenum, args[0], args[cur_arg + 1 ]);
2120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
2122 }
2123
2124 curproxy->listen->perm.ux.uid = user->pw_uid;
2125 cur_arg += 2;
2126 continue;
2127 }
2128
2129 if (!strcmp(args[cur_arg], "group")) {
2130 struct group *group;
2131
2132 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2133 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2134 file, linenum, args[0], args[cur_arg]);
2135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
2137 }
2138 group = getgrnam(args[cur_arg + 1]);
2139 if (!group) {
2140 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2141 file, linenum, args[0], args[cur_arg + 1 ]);
2142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
2144 }
2145
2146 curproxy->listen->perm.ux.gid = group->gr_gid;
2147 cur_arg += 2;
2148 continue;
2149 }
2150
Willy Tarreaub48f9582011-09-05 01:17:06 +02002151 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 +01002152 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002155 }
Willy Tarreau93893792009-07-23 13:19:11 +02002156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002157 }
2158 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2159 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2160 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2161 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002165 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002167
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 /* flush useless bits */
2169 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002172 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002173 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002175
Willy Tarreau1c47f852006-07-09 08:22:27 +02002176 if (!*args[1]) {
2177 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2178 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002181 }
2182
Willy Tarreaua534fea2008-08-03 12:19:50 +02002183 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002184 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002185 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002186 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002187 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2188
Willy Tarreau93893792009-07-23 13:19:11 +02002189 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2192 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2193 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2194 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2195 else {
2196 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
2200 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002201 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002202 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002203
2204 if (curproxy == &defproxy) {
2205 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002209 }
2210
2211 if (!*args[1]) {
2212 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002216 }
2217
2218 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002219 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002220
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002221 if (curproxy->uuid <= 0) {
2222 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002226 }
2227
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002228 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2229 if (node) {
2230 struct proxy *target = container_of(node, struct proxy, conf.id);
2231 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2232 file, linenum, proxy_type_str(curproxy), curproxy->id,
2233 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002238 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002239 else if (!strcmp(args[0], "description")) {
2240 int i, len=0;
2241 char *d;
2242
Cyril Bonté99ed3272010-01-24 23:29:44 +01002243 if (curproxy == &defproxy) {
2244 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2245 file, linenum, args[0]);
2246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
2248 }
2249
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002250 if (!*args[1]) {
2251 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2252 file, linenum, args[0]);
2253 return -1;
2254 }
2255
2256 for(i=1; *args[i]; i++)
2257 len += strlen(args[i])+1;
2258
2259 d = (char *)calloc(1, len);
2260 curproxy->desc = d;
2261
2262 d += sprintf(d, "%s", args[1]);
2263 for(i=2; *args[i]; i++)
2264 d += sprintf(d, " %s", args[i]);
2265
2266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2268 curproxy->state = PR_STSTOPPED;
2269 }
2270 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2271 curproxy->state = PR_STNEW;
2272 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002273 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2274 int cur_arg = 1;
2275 unsigned int set = 0;
2276
2277 while (*args[cur_arg]) {
2278 int u;
2279 if (strcmp(args[cur_arg], "all") == 0) {
2280 set = 0;
2281 break;
2282 }
2283 else if (strcmp(args[cur_arg], "odd") == 0) {
2284 set |= 0x55555555;
2285 }
2286 else if (strcmp(args[cur_arg], "even") == 0) {
2287 set |= 0xAAAAAAAA;
2288 }
2289 else {
2290 u = str2uic(args[cur_arg]);
2291 if (u < 1 || u > 32) {
2292 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2293 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002296 }
2297 if (u > global.nbproc) {
2298 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002301 }
2302 set |= 1 << (u - 1);
2303 }
2304 cur_arg++;
2305 }
2306 curproxy->bind_proc = set;
2307 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002308 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002309 if (curproxy == &defproxy) {
2310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002313 }
2314
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002315 err = invalid_char(args[1]);
2316 if (err) {
2317 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2318 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002320 }
2321
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002322 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2323 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2324 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002327 }
2328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2330 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002334
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 if (*(args[1]) == 0) {
2336 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002341
Willy Tarreau67402132012-05-31 20:40:20 +02002342 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002343 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002344 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->cookie_name = strdup(args[1]);
2347 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002348
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 cur_arg = 2;
2350 while (*(args[cur_arg])) {
2351 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002352 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002355 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002358 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
2360 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002361 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002364 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002366 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002367 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002370 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002372 else if (!strcmp(args[cur_arg], "httponly")) {
2373 curproxy->ck_opts |= PR_CK_HTTPONLY;
2374 }
2375 else if (!strcmp(args[cur_arg], "secure")) {
2376 curproxy->ck_opts |= PR_CK_SECURE;
2377 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002378 else if (!strcmp(args[cur_arg], "domain")) {
2379 if (!*args[cur_arg + 1]) {
2380 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2381 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002384 }
2385
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002386 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002387 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002388 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2389 " dots nor does not start with a dot."
2390 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002391 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002392 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002393 }
2394
2395 err = invalid_domainchar(args[cur_arg + 1]);
2396 if (err) {
2397 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2398 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002401 }
2402
Willy Tarreau68a897b2009-12-03 23:28:34 +01002403 if (!curproxy->cookie_domain) {
2404 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2405 } else {
2406 /* one domain was already specified, add another one by
2407 * building the string which will be returned along with
2408 * the cookie.
2409 */
2410 char *new_ptr;
2411 int new_len = strlen(curproxy->cookie_domain) +
2412 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2413 new_ptr = malloc(new_len);
2414 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2415 free(curproxy->cookie_domain);
2416 curproxy->cookie_domain = new_ptr;
2417 }
Willy Tarreau31936852010-10-06 16:59:56 +02002418 cur_arg++;
2419 }
2420 else if (!strcmp(args[cur_arg], "maxidle")) {
2421 unsigned int maxidle;
2422 const char *res;
2423
2424 if (!*args[cur_arg + 1]) {
2425 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2426 file, linenum, args[cur_arg]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2432 if (res) {
2433 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2434 file, linenum, *res, args[cur_arg]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curproxy->cookie_maxidle = maxidle;
2439 cur_arg++;
2440 }
2441 else if (!strcmp(args[cur_arg], "maxlife")) {
2442 unsigned int maxlife;
2443 const char *res;
2444
2445 if (!*args[cur_arg + 1]) {
2446 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2447 file, linenum, args[cur_arg]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
2452 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2453 if (res) {
2454 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2455 file, linenum, *res, args[cur_arg]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002460 cur_arg++;
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002463 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 +02002464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 cur_arg++;
2469 }
Willy Tarreau67402132012-05-31 20:40:20 +02002470 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2472 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475
Willy Tarreau67402132012-05-31 20:40:20 +02002476 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002481
Willy Tarreau67402132012-05-31 20:40:20 +02002482 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002483 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2484 file, linenum);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002488 else if (!strcmp(args[0], "persist")) { /* persist */
2489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : missing persist method.\n",
2491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002494 }
2495
2496 if (!strncmp(args[1], "rdp-cookie", 10)) {
2497 curproxy->options2 |= PR_O2_RDPC_PRST;
2498
Emeric Brunb982a3d2010-01-04 15:45:53 +01002499 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002500 const char *beg, *end;
2501
2502 beg = args[1] + 11;
2503 end = strchr(beg, ')');
2504
2505 if (!end || end == beg) {
2506 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002510 }
2511
2512 free(curproxy->rdp_cookie_name);
2513 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2514 curproxy->rdp_cookie_len = end-beg;
2515 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002516 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002517 free(curproxy->rdp_cookie_name);
2518 curproxy->rdp_cookie_name = strdup("msts");
2519 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2520 }
2521 else { /* syntax */
2522 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002526 }
2527 }
2528 else {
2529 Alert("parsing [%s:%d] : unknown persist method.\n",
2530 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002533 }
2534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002536 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002548 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002554 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 curproxy->appsession_name = strdup(args[1]);
2556 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2557 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002558 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2559 if (err) {
2560 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2561 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002564 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002565 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002566
Willy Tarreau51041c72007-09-09 21:56:53 +02002567 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002572
2573 cur_arg = 6;
2574 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002575 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2576 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002577 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002578 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002579 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002580 } else if (!strcmp(args[cur_arg], "prefix")) {
2581 curproxy->options2 |= PR_O2_AS_PFX;
2582 } else if (!strcmp(args[cur_arg], "mode")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2585 file, linenum, args[0], args[cur_arg]);
2586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
2588 }
2589
2590 cur_arg++;
2591 if (!strcmp(args[cur_arg], "query-string")) {
2592 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2593 curproxy->options2 |= PR_O2_AS_M_QS;
2594 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2595 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2596 curproxy->options2 |= PR_O2_AS_M_PP;
2597 } else {
2598 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002603 cur_arg++;
2604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 } /* Url App Session */
2606 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002607 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[4]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002623 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 curproxy->capture_name = strdup(args[2]);
2625 curproxy->capture_namelen = strlen(curproxy->capture_name);
2626 curproxy->capture_len = atol(args[4]);
2627 if (curproxy->capture_len >= CAPTURE_LEN) {
2628 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2629 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 curproxy->capture_len = CAPTURE_LEN - 1;
2632 }
2633 curproxy->to_log |= LW_COOKIE;
2634 }
2635 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2636 struct cap_hdr *hdr;
2637
2638 if (curproxy == &defproxy) {
2639 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 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 }
2643
2644 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2645 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2646 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
2650
2651 hdr = calloc(sizeof(struct cap_hdr), 1);
2652 hdr->next = curproxy->req_cap;
2653 hdr->name = strdup(args[3]);
2654 hdr->namelen = strlen(args[3]);
2655 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002656 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 hdr->index = curproxy->nb_req_cap++;
2658 curproxy->req_cap = hdr;
2659 curproxy->to_log |= LW_REQHDR;
2660 }
2661 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2662 struct cap_hdr *hdr;
2663
2664 if (curproxy == &defproxy) {
2665 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 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002668 }
2669
2670 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2671 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2672 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 }
2676 hdr = calloc(sizeof(struct cap_hdr), 1);
2677 hdr->next = curproxy->rsp_cap;
2678 hdr->name = strdup(args[3]);
2679 hdr->namelen = strlen(args[3]);
2680 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002681 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 hdr->index = curproxy->nb_rsp_cap++;
2683 curproxy->rsp_cap = hdr;
2684 curproxy->to_log |= LW_RSPHDR;
2685 }
2686 else {
2687 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002694 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002695 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002696
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 if (*(args[1]) == 0) {
2698 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
2703 curproxy->conn_retries = atol(args[1]);
2704 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002705 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002706 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002707
2708 if (curproxy == &defproxy) {
2709 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713
Willy Tarreauff011f22011-01-06 17:51:27 +01002714 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 +01002715 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2716 file, linenum, args[0]);
2717 err_code |= ERR_WARN;
2718 }
2719
Willy Tarreauff011f22011-01-06 17:51:27 +01002720 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002721
Willy Tarreauff011f22011-01-06 17:51:27 +01002722 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002723 err_code |= ERR_ALERT | ERR_ABORT;
2724 goto out;
2725 }
2726
Willy Tarreauff011f22011-01-06 17:51:27 +01002727 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2728 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002729 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002730 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2731 /* set the header name and length into the proxy structure */
2732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2733 err_code |= ERR_WARN;
2734
2735 if (!*args[1]) {
2736 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2737 file, linenum, args[0]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741
2742 /* set the desired header name */
2743 free(curproxy->server_id_hdr_name);
2744 curproxy->server_id_hdr_name = strdup(args[1]);
2745 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2746 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002747 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002748 if (curproxy == &defproxy) {
2749 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002752 }
2753
Willy Tarreauef6494c2010-01-28 17:12:36 +01002754 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002755 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2756 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002759 }
2760
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002761 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2762 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2763 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002766 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002767
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002768 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002769 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002770 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002771 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002772 struct redirect_rule *rule;
2773 int cur_arg;
2774 int type = REDIRECT_TYPE_NONE;
2775 int code = 302;
2776 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002777 char *cookie = NULL;
2778 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002779 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002780
Cyril Bonté99ed3272010-01-24 23:29:44 +01002781 if (curproxy == &defproxy) {
2782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002787 cur_arg = 1;
2788 while (*(args[cur_arg])) {
2789 if (!strcmp(args[cur_arg], "location")) {
2790 if (!*args[cur_arg + 1]) {
2791 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2792 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002795 }
2796
2797 type = REDIRECT_TYPE_LOCATION;
2798 cur_arg++;
2799 destination = args[cur_arg];
2800 }
2801 else if (!strcmp(args[cur_arg], "prefix")) {
2802 if (!*args[cur_arg + 1]) {
2803 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2804 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002807 }
2808
2809 type = REDIRECT_TYPE_PREFIX;
2810 cur_arg++;
2811 destination = args[cur_arg];
2812 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002813 else if (!strcmp(args[cur_arg], "set-cookie")) {
2814 if (!*args[cur_arg + 1]) {
2815 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2816 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002819 }
2820
2821 cur_arg++;
2822 cookie = args[cur_arg];
2823 cookie_set = 1;
2824 }
2825 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2826 if (!*args[cur_arg + 1]) {
2827 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2828 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002831 }
2832
2833 cur_arg++;
2834 cookie = args[cur_arg];
2835 cookie_set = 0;
2836 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002837 else if (!strcmp(args[cur_arg],"code")) {
2838 if (!*args[cur_arg + 1]) {
2839 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2840 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002843 }
2844 cur_arg++;
2845 code = atol(args[cur_arg]);
2846 if (code < 301 || code > 303) {
2847 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2848 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002851 }
2852 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002853 else if (!strcmp(args[cur_arg],"drop-query")) {
2854 flags |= REDIRECT_FLAG_DROP_QS;
2855 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002856 else if (!strcmp(args[cur_arg],"append-slash")) {
2857 flags |= REDIRECT_FLAG_APPEND_SLASH;
2858 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002859 else if (strcmp(args[cur_arg], "if") == 0 ||
2860 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002861 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002862 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002863 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2864 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002868 break;
2869 }
2870 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002871 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 +02002872 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002875 }
2876 cur_arg++;
2877 }
2878
2879 if (type == REDIRECT_TYPE_NONE) {
2880 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2881 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002884 }
2885
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002886 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2887 rule->cond = cond;
2888 rule->rdr_str = strdup(destination);
2889 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002890 if (cookie) {
2891 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002892 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002893 */
2894 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002895 if (cookie_set) {
2896 rule->cookie_str = malloc(rule->cookie_len + 10);
2897 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2898 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2899 rule->cookie_len += 9;
2900 } else {
2901 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002902 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002903 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2904 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002905 }
2906 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002907 rule->type = type;
2908 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002909 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002910 LIST_INIT(&rule->list);
2911 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002912 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2913 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002914 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002915 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002916 struct switching_rule *rule;
2917
Willy Tarreaub099aca2008-10-12 17:26:37 +02002918 if (curproxy == &defproxy) {
2919 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002922 }
2923
Willy Tarreau55ea7572007-06-17 19:56:27 +02002924 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002925 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002926
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002931 }
2932
Willy Tarreauef6494c2010-01-28 17:12:36 +01002933 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002934 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2935 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002938 }
2939
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002940 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2941 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2942 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002945 }
2946
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002947 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002948
Willy Tarreau55ea7572007-06-17 19:56:27 +02002949 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2950 rule->cond = cond;
2951 rule->be.name = strdup(args[1]);
2952 LIST_INIT(&rule->list);
2953 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2954 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002955 else if (strcmp(args[0], "use-server") == 0) {
2956 struct server_rule *rule;
2957
2958 if (curproxy == &defproxy) {
2959 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
2964 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2965 err_code |= ERR_WARN;
2966
2967 if (*(args[1]) == 0) {
2968 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972
2973 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2974 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2975 file, linenum, args[0]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002980 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2981 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2982 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986
2987 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2988
2989 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2990 rule->cond = cond;
2991 rule->srv.name = strdup(args[1]);
2992 LIST_INIT(&rule->list);
2993 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2994 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2995 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002996 else if ((!strcmp(args[0], "force-persist")) ||
2997 (!strcmp(args[0], "ignore-persist"))) {
2998 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002999
3000 if (curproxy == &defproxy) {
3001 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005
3006 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3007 err_code |= ERR_WARN;
3008
Willy Tarreauef6494c2010-01-28 17:12:36 +01003009 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003010 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3011 file, linenum, args[0]);
3012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
3014 }
3015
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003016 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3017 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3018 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003023 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003024
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003025 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003026 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003027 if (!strcmp(args[0], "force-persist")) {
3028 rule->type = PERSIST_TYPE_FORCE;
3029 } else {
3030 rule->type = PERSIST_TYPE_IGNORE;
3031 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003032 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003033 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003034 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 else if (!strcmp(args[0], "stick-table")) {
3036 int myidx = 1;
3037
Emeric Brun32da3c42010-09-23 18:39:19 +02003038 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 curproxy->table.type = (unsigned int)-1;
3040 while (*args[myidx]) {
3041 const char *err;
3042
3043 if (strcmp(args[myidx], "size") == 0) {
3044 myidx++;
3045 if (!*(args[myidx])) {
3046 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3047 file, linenum, args[myidx-1]);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
3051 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3052 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3053 file, linenum, *err, args[myidx-1]);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003057 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003059 else if (strcmp(args[myidx], "peers") == 0) {
3060 myidx++;
3061 if (!*(args[myidx])) {
3062 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3063 file, linenum, args[myidx-1]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067 curproxy->table.peers.name = strdup(args[myidx++]);
3068 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 else if (strcmp(args[myidx], "expire") == 0) {
3070 myidx++;
3071 if (!*(args[myidx])) {
3072 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3073 file, linenum, args[myidx-1]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3078 if (err) {
3079 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3080 file, linenum, *err, args[myidx-1]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003085 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003086 }
3087 else if (strcmp(args[myidx], "nopurge") == 0) {
3088 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003089 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003090 }
3091 else if (strcmp(args[myidx], "type") == 0) {
3092 myidx++;
3093 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3094 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3095 file, linenum, args[myidx]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003099 /* myidx already points to next arg */
3100 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003101 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003102 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003103 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003104
3105 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003106 nw = args[myidx];
3107 while (*nw) {
3108 /* the "store" keyword supports a comma-separated list */
3109 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003110 sa = NULL; /* store arg */
3111 while (*nw && *nw != ',') {
3112 if (*nw == '(') {
3113 *nw = 0;
3114 sa = ++nw;
3115 while (*nw != ')') {
3116 if (!*nw) {
3117 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3118 file, linenum, args[0], cw);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
3122 nw++;
3123 }
3124 *nw = '\0';
3125 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003126 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003127 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003128 if (*nw)
3129 *nw++ = '\0';
3130 type = stktable_get_data_type(cw);
3131 if (type < 0) {
3132 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3133 file, linenum, args[0], cw);
3134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
Willy Tarreauac782882010-06-20 10:41:54 +02003137
3138 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3139 switch (err) {
3140 case PE_NONE: break;
3141 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003142 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3143 file, linenum, args[0], cw);
3144 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003145 break;
3146
3147 case PE_ARG_MISSING:
3148 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3149 file, linenum, args[0], cw);
3150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
3152
3153 case PE_ARG_NOT_USED:
3154 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3155 file, linenum, args[0], cw);
3156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
3158
3159 default:
3160 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3161 file, linenum, args[0], cw);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003164 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003165 }
3166 myidx++;
3167 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003168 else {
3169 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3170 file, linenum, args[myidx]);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003173 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 }
3175
3176 if (!curproxy->table.size) {
3177 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3178 file, linenum);
3179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
3181 }
3182
3183 if (curproxy->table.type == (unsigned int)-1) {
3184 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3185 file, linenum);
3186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
3188 }
3189 }
3190 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003191 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003192 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003193 int myidx = 0;
3194 const char *name = NULL;
3195 int flags;
3196
3197 if (curproxy == &defproxy) {
3198 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
3201 }
3202
3203 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3204 err_code |= ERR_WARN;
3205 goto out;
3206 }
3207
3208 myidx++;
3209 if ((strcmp(args[myidx], "store") == 0) ||
3210 (strcmp(args[myidx], "store-request") == 0)) {
3211 myidx++;
3212 flags = STK_IS_STORE;
3213 }
3214 else if (strcmp(args[myidx], "store-response") == 0) {
3215 myidx++;
3216 flags = STK_IS_STORE | STK_ON_RSP;
3217 }
3218 else if (strcmp(args[myidx], "match") == 0) {
3219 myidx++;
3220 flags = STK_IS_MATCH;
3221 }
3222 else if (strcmp(args[myidx], "on") == 0) {
3223 myidx++;
3224 flags = STK_IS_MATCH | STK_IS_STORE;
3225 }
3226 else {
3227 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
3231
3232 if (*(args[myidx]) == 0) {
3233 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237
David du Colombier7af46052012-05-16 14:16:48 +02003238 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003239 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003240 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
3243 }
3244
3245 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003246 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3248 file, linenum, args[0], expr->fetch->kw);
3249 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003250 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003251 goto out;
3252 }
3253 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003254 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003255 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3256 file, linenum, args[0], expr->fetch->kw);
3257 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003258 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003259 goto out;
3260 }
3261 }
3262
3263 if (strcmp(args[myidx], "table") == 0) {
3264 myidx++;
3265 name = args[myidx++];
3266 }
3267
Willy Tarreauef6494c2010-01-28 17:12:36 +01003268 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003269 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3270 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3271 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003272 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003273 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003274 goto out;
3275 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003276 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003277 else if (*(args[myidx])) {
3278 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3279 file, linenum, args[0], args[myidx]);
3280 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003281 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003282 goto out;
3283 }
Emeric Brun97679e72010-09-23 17:56:44 +02003284 if (flags & STK_ON_RSP)
3285 err_code |= warnif_cond_requires_req(cond, file, linenum);
3286 else
3287 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003288
Emeric Brunb982a3d2010-01-04 15:45:53 +01003289 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3290 rule->cond = cond;
3291 rule->expr = expr;
3292 rule->flags = flags;
3293 rule->table.name = name ? strdup(name) : NULL;
3294 LIST_INIT(&rule->list);
3295 if (flags & STK_ON_RSP)
3296 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3297 else
3298 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003302 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003303
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3305 curproxy->uri_auth = NULL; /* we must detach from the default config */
3306
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003307 if (!*args[1]) {
3308 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003309 } else if (!strcmp(args[1], "admin")) {
3310 struct stats_admin_rule *rule;
3311
3312 if (curproxy == &defproxy) {
3313 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
3316 }
3317
3318 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3319 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3320 err_code |= ERR_ALERT | ERR_ABORT;
3321 goto out;
3322 }
3323
3324 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3325 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3326 file, linenum, args[0], args[1]);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003330 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3331 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3332 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
3336
3337 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3338
3339 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3340 rule->cond = cond;
3341 LIST_INIT(&rule->list);
3342 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 } else if (!strcmp(args[1], "uri")) {
3344 if (*(args[2]) == 0) {
3345 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3349 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_ABORT;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
3353 } else if (!strcmp(args[1], "realm")) {
3354 if (*(args[2]) == 0) {
3355 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_ABORT;
3361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003363 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003364 unsigned interval;
3365
3366 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3367 if (err) {
3368 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3369 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003372 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003374 err_code |= ERR_ALERT | ERR_ABORT;
3375 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003376 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003377 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003378 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003379
3380 if (curproxy == &defproxy) {
3381 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385
3386 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3387 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3388 err_code |= ERR_ALERT | ERR_ABORT;
3389 goto out;
3390 }
3391
Willy Tarreauff011f22011-01-06 17:51:27 +01003392 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3393 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003394 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3395 file, linenum, args[0]);
3396 err_code |= ERR_WARN;
3397 }
3398
Willy Tarreauff011f22011-01-06 17:51:27 +01003399 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003400
Willy Tarreauff011f22011-01-06 17:51:27 +01003401 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003402 err_code |= ERR_ALERT | ERR_ABORT;
3403 goto out;
3404 }
3405
Willy Tarreauff011f22011-01-06 17:51:27 +01003406 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3407 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003408
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 } else if (!strcmp(args[1], "auth")) {
3410 if (*(args[2]) == 0) {
3411 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_FATAL;
3413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3415 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_ABORT;
3417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419 } else if (!strcmp(args[1], "scope")) {
3420 if (*(args[2]) == 0) {
3421 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_ABORT;
3427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
3429 } else if (!strcmp(args[1], "enable")) {
3430 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_ALERT | ERR_ABORT;
3433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003435 } else if (!strcmp(args[1], "hide-version")) {
3436 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3437 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003438 err_code |= ERR_ALERT | ERR_ABORT;
3439 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003440 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003441 } else if (!strcmp(args[1], "show-legends")) {
3442 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3443 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3444 err_code |= ERR_ALERT | ERR_ABORT;
3445 goto out;
3446 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003447 } else if (!strcmp(args[1], "show-node")) {
3448
3449 if (*args[2]) {
3450 int i;
3451 char c;
3452
3453 for (i=0; args[2][i]; i++) {
3454 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003455 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3456 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003457 break;
3458 }
3459
3460 if (!i || args[2][i]) {
3461 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3462 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3463 file, linenum, args[0], args[1]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 }
3468
3469 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3470 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
3473 }
3474 } else if (!strcmp(args[1], "show-desc")) {
3475 char *desc = NULL;
3476
3477 if (*args[2]) {
3478 int i, len=0;
3479 char *d;
3480
3481 for(i=2; *args[i]; i++)
3482 len += strlen(args[i])+1;
3483
3484 desc = d = (char *)calloc(1, len);
3485
3486 d += sprintf(d, "%s", args[2]);
3487 for(i=3; *args[i]; i++)
3488 d += sprintf(d, " %s", args[i]);
3489 }
3490
3491 if (!*args[2] && !global.desc)
3492 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3493 file, linenum, args[1]);
3494 else {
3495 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3496 free(desc);
3497 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3498 err_code |= ERR_ALERT | ERR_ABORT;
3499 goto out;
3500 }
3501 free(desc);
3502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003504stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003505 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 +01003506 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 }
3510 }
3511 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003512 int optnum;
3513
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003514 if (*(args[1]) == '\0') {
3515 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003520
3521 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3522 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003523 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3524 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3525 file, linenum, cfg_opts[optnum].name);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
Willy Tarreau93893792009-07-23 13:19:11 +02003529 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3530 err_code |= ERR_WARN;
3531 goto out;
3532 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003533
Willy Tarreau3842f002009-06-14 11:39:52 +02003534 curproxy->no_options &= ~cfg_opts[optnum].val;
3535 curproxy->options &= ~cfg_opts[optnum].val;
3536
3537 switch (kwm) {
3538 case KWM_STD:
3539 curproxy->options |= cfg_opts[optnum].val;
3540 break;
3541 case KWM_NO:
3542 curproxy->no_options |= cfg_opts[optnum].val;
3543 break;
3544 case KWM_DEF: /* already cleared */
3545 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003546 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003547
Willy Tarreau93893792009-07-23 13:19:11 +02003548 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003549 }
3550 }
3551
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003552 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3553 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003554 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3555 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3556 file, linenum, cfg_opts2[optnum].name);
3557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
3559 }
Willy Tarreau93893792009-07-23 13:19:11 +02003560 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3561 err_code |= ERR_WARN;
3562 goto out;
3563 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003564
Willy Tarreau3842f002009-06-14 11:39:52 +02003565 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3566 curproxy->options2 &= ~cfg_opts2[optnum].val;
3567
3568 switch (kwm) {
3569 case KWM_STD:
3570 curproxy->options2 |= cfg_opts2[optnum].val;
3571 break;
3572 case KWM_NO:
3573 curproxy->no_options2 |= cfg_opts2[optnum].val;
3574 break;
3575 case KWM_DEF: /* already cleared */
3576 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003577 }
Willy Tarreau93893792009-07-23 13:19:11 +02003578 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003579 }
3580 }
3581
Willy Tarreau3842f002009-06-14 11:39:52 +02003582 if (kwm != KWM_STD) {
3583 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003584 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003587 }
3588
Emeric Brun3a058f32009-06-30 18:26:00 +02003589 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003590 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003592 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003593 if (*(args[2]) != '\0') {
3594 if (!strcmp(args[2], "clf")) {
3595 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003596 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003597 } else {
3598 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003601 }
3602 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003603 if (curproxy->logformat_string != default_http_log_format &&
3604 curproxy->logformat_string != default_tcp_log_format &&
3605 curproxy->logformat_string != clf_http_log_format)
3606 free(curproxy->logformat_string);
3607 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003608 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003609 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003611 if (curproxy->logformat_string != default_http_log_format &&
3612 curproxy->logformat_string != default_tcp_log_format &&
3613 curproxy->logformat_string != clf_http_log_format)
3614 free(curproxy->logformat_string);
3615 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 else if (!strcmp(args[1], "tcpka")) {
3618 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003619 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003621
3622 if (curproxy->cap & PR_CAP_FE)
3623 curproxy->options |= PR_O_TCP_CLI_KA;
3624 if (curproxy->cap & PR_CAP_BE)
3625 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 }
3627 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_WARN;
3630
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003632 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003633 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003634 curproxy->options2 &= ~PR_O2_CHK_ANY;
3635 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 if (!*args[2]) { /* no argument */
3637 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3638 curproxy->check_len = strlen(DEF_CHECK_REQ);
3639 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003640 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 curproxy->check_req = (char *)malloc(reqlen);
3642 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003643 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003645 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 if (*args[4])
3647 reqlen += strlen(args[4]);
3648 else
3649 reqlen += strlen("HTTP/1.0");
3650
3651 curproxy->check_req = (char *)malloc(reqlen);
3652 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003653 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003655 }
3656 else if (!strcmp(args[1], "ssl-hello-chk")) {
3657 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003660
Willy Tarreaua534fea2008-08-03 12:19:50 +02003661 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003663 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003664 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
Willy Tarreau23677902007-05-08 23:50:35 +02003666 else if (!strcmp(args[1], "smtpchk")) {
3667 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003668 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003669 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003670 curproxy->options2 &= ~PR_O2_CHK_ANY;
3671 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003672
3673 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3674 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3675 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3676 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3677 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3678 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3679 curproxy->check_req = (char *)malloc(reqlen);
3680 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3681 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3682 } else {
3683 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3684 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3685 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3686 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3687 }
3688 }
3689 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003690 else if (!strcmp(args[1], "pgsql-check")) {
3691 /* use PostgreSQL request to check servers' health */
3692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3693 err_code |= ERR_WARN;
3694
3695 free(curproxy->check_req);
3696 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003697 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003698 curproxy->options2 |= PR_O2_PGSQL_CHK;
3699
3700 if (*(args[2])) {
3701 int cur_arg = 2;
3702
3703 while (*(args[cur_arg])) {
3704 if (strcmp(args[cur_arg], "user") == 0) {
3705 char * packet;
3706 uint32_t packet_len;
3707 uint32_t pv;
3708
3709 /* suboption header - needs additional argument for it */
3710 if (*(args[cur_arg+1]) == 0) {
3711 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3712 file, linenum, args[0], args[1], args[cur_arg]);
3713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
3715 }
3716
3717 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3718 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3719 pv = htonl(0x30000); /* protocol version 3.0 */
3720
3721 packet = (char*) calloc(1, packet_len);
3722
3723 memcpy(packet + 4, &pv, 4);
3724
3725 /* copy "user" */
3726 memcpy(packet + 8, "user", 4);
3727
3728 /* copy username */
3729 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3730
3731 free(curproxy->check_req);
3732 curproxy->check_req = packet;
3733 curproxy->check_len = packet_len;
3734
3735 packet_len = htonl(packet_len);
3736 memcpy(packet, &packet_len, 4);
3737 cur_arg += 2;
3738 } else {
3739 /* unknown suboption - catchall */
3740 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3741 file, linenum, args[0], args[1]);
3742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
3744 }
3745 } /* end while loop */
3746 }
3747 }
3748
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003749 else if (!strcmp(args[1], "redis-check")) {
3750 /* use REDIS PING request to check servers' health */
3751 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3752 err_code |= ERR_WARN;
3753
3754 free(curproxy->check_req);
3755 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003756 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003757 curproxy->options2 |= PR_O2_REDIS_CHK;
3758
3759 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3760 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3761 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3762 }
3763
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003764 else if (!strcmp(args[1], "mysql-check")) {
3765 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003766 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3767 err_code |= ERR_WARN;
3768
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003769 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003770 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003771 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003772 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003773
3774 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3775 * const char mysql40_client_auth_pkt[] = {
3776 * "\x0e\x00\x00" // packet length
3777 * "\x01" // packet number
3778 * "\x00\x00" // client capabilities
3779 * "\x00\x00\x01" // max packet
3780 * "haproxy\x00" // username (null terminated string)
3781 * "\x00" // filler (always 0x00)
3782 * "\x01\x00\x00" // packet length
3783 * "\x00" // packet number
3784 * "\x01" // COM_QUIT command
3785 * };
3786 */
3787
3788 if (*(args[2])) {
3789 int cur_arg = 2;
3790
3791 while (*(args[cur_arg])) {
3792 if (strcmp(args[cur_arg], "user") == 0) {
3793 char *mysqluser;
3794 int packetlen, reqlen, userlen;
3795
3796 /* suboption header - needs additional argument for it */
3797 if (*(args[cur_arg+1]) == 0) {
3798 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3799 file, linenum, args[0], args[1], args[cur_arg]);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803 mysqluser = args[cur_arg + 1];
3804 userlen = strlen(mysqluser);
3805 packetlen = userlen + 7;
3806 reqlen = packetlen + 9;
3807
3808 free(curproxy->check_req);
3809 curproxy->check_req = (char *)calloc(1, reqlen);
3810 curproxy->check_len = reqlen;
3811
3812 snprintf(curproxy->check_req, 4, "%c%c%c",
3813 ((unsigned char) packetlen & 0xff),
3814 ((unsigned char) (packetlen >> 8) & 0xff),
3815 ((unsigned char) (packetlen >> 16) & 0xff));
3816
3817 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003818 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003819 curproxy->check_req[8] = 1;
3820 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3821 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3822 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3823 cur_arg += 2;
3824 } else {
3825 /* unknown suboption - catchall */
3826 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3827 file, linenum, args[0], args[1]);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 } /* end while loop */
3832 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003833 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003834 else if (!strcmp(args[1], "ldap-check")) {
3835 /* use LDAP request to check servers' health */
3836 free(curproxy->check_req);
3837 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003838 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003839 curproxy->options2 |= PR_O2_LDAP_CHK;
3840
3841 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3842 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3843 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3844 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003845 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003846 int cur_arg;
3847
3848 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3849 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003850 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003851
Willy Tarreau87cf5142011-08-19 22:57:24 +02003852 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003853
3854 free(curproxy->fwdfor_hdr_name);
3855 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3856 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3857
3858 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3859 cur_arg = 2;
3860 while (*(args[cur_arg])) {
3861 if (!strcmp(args[cur_arg], "except")) {
3862 /* suboption except - needs additional argument for it */
3863 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3864 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3865 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003868 }
3869 /* flush useless bits */
3870 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003871 cur_arg += 2;
3872 } else if (!strcmp(args[cur_arg], "header")) {
3873 /* suboption header - needs additional argument for it */
3874 if (*(args[cur_arg+1]) == 0) {
3875 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3876 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003879 }
3880 free(curproxy->fwdfor_hdr_name);
3881 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3882 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3883 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003884 } else if (!strcmp(args[cur_arg], "if-none")) {
3885 curproxy->options &= ~PR_O_FF_ALWAYS;
3886 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003887 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003888 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003889 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003893 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003894 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003895 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003896 else if (!strcmp(args[1], "originalto")) {
3897 int cur_arg;
3898
3899 /* insert x-original-to field, but not for the IP address listed as an except.
3900 * set default options (ie: bitfield, header name, etc)
3901 */
3902
3903 curproxy->options |= PR_O_ORGTO;
3904
3905 free(curproxy->orgto_hdr_name);
3906 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3907 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3908
Willy Tarreau87cf5142011-08-19 22:57:24 +02003909 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003910 cur_arg = 2;
3911 while (*(args[cur_arg])) {
3912 if (!strcmp(args[cur_arg], "except")) {
3913 /* suboption except - needs additional argument for it */
3914 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3915 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3916 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003919 }
3920 /* flush useless bits */
3921 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3922 cur_arg += 2;
3923 } else if (!strcmp(args[cur_arg], "header")) {
3924 /* suboption header - needs additional argument for it */
3925 if (*(args[cur_arg+1]) == 0) {
3926 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3927 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003930 }
3931 free(curproxy->orgto_hdr_name);
3932 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3933 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3934 cur_arg += 2;
3935 } else {
3936 /* unknown suboption - catchall */
3937 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3938 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003941 }
3942 } /* end while loop */
3943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 else {
3945 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
Willy Tarreau93893792009-07-23 13:19:11 +02003949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003951 else if (!strcmp(args[0], "default_backend")) {
3952 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003954
3955 if (*(args[1]) == 0) {
3956 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003959 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003960 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003961 curproxy->defbe.name = strdup(args[1]);
3962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003964 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003966
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003967 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3968 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 /* enable reconnections to dispatch */
3971 curproxy->options |= PR_O_REDISP;
3972 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003973 else if (!strcmp(args[0], "http-check")) {
3974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003976
3977 if (strcmp(args[1], "disable-on-404") == 0) {
3978 /* enable a graceful server shutdown on an HTTP 404 response */
3979 curproxy->options |= PR_O_DISABLE404;
3980 }
Willy Tarreauef781042010-01-27 11:53:01 +01003981 else if (strcmp(args[1], "send-state") == 0) {
3982 /* enable emission of the apparent state of a server in HTTP checks */
3983 curproxy->options2 |= PR_O2_CHK_SNDST;
3984 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003985 else if (strcmp(args[1], "expect") == 0) {
3986 const char *ptr_arg;
3987 int cur_arg;
3988
3989 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3990 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
3993 }
3994
3995 cur_arg = 2;
3996 /* consider exclamation marks, sole or at the beginning of a word */
3997 while (*(ptr_arg = args[cur_arg])) {
3998 while (*ptr_arg == '!') {
3999 curproxy->options2 ^= PR_O2_EXP_INV;
4000 ptr_arg++;
4001 }
4002 if (*ptr_arg)
4003 break;
4004 cur_arg++;
4005 }
4006 /* now ptr_arg points to the beginning of a word past any possible
4007 * exclamation mark, and cur_arg is the argument which holds this word.
4008 */
4009 if (strcmp(ptr_arg, "status") == 0) {
4010 if (!*(args[cur_arg + 1])) {
4011 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4012 file, linenum, args[0], args[1], ptr_arg);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
4016 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004017 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004018 curproxy->expect_str = strdup(args[cur_arg + 1]);
4019 }
4020 else if (strcmp(ptr_arg, "string") == 0) {
4021 if (!*(args[cur_arg + 1])) {
4022 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4023 file, linenum, args[0], args[1], ptr_arg);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004028 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004029 curproxy->expect_str = strdup(args[cur_arg + 1]);
4030 }
4031 else if (strcmp(ptr_arg, "rstatus") == 0) {
4032 if (!*(args[cur_arg + 1])) {
4033 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4034 file, linenum, args[0], args[1], ptr_arg);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004039 free(curproxy->expect_str);
4040 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4041 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004042 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4043 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4044 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4045 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049 }
4050 else if (strcmp(ptr_arg, "rstring") == 0) {
4051 if (!*(args[cur_arg + 1])) {
4052 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4053 file, linenum, args[0], args[1], ptr_arg);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056 }
4057 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004058 free(curproxy->expect_str);
4059 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4060 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004061 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4062 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4063 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4064 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068 }
4069 else {
4070 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4071 file, linenum, args[0], args[1], ptr_arg);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004076 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004077 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 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004080 }
4081 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004082 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004083 if (curproxy == &defproxy) {
4084 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004087 }
4088
Willy Tarreaub80c2302007-11-30 20:51:32 +01004089 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004091
4092 if (strcmp(args[1], "fail") == 0) {
4093 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004094 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004095 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4096 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004099 }
4100
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004101 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4102 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4103 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004106 }
4107 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4108 }
4109 else {
4110 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004113 }
4114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115#ifdef TPROXY
4116 else if (!strcmp(args[0], "transparent")) {
4117 /* enable transparent proxy connections */
4118 curproxy->options |= PR_O_TRANSP;
4119 }
4120#endif
4121 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004122 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004124
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 if (*(args[1]) == 0) {
4126 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 }
4130 curproxy->maxconn = atol(args[1]);
4131 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004132 else if (!strcmp(args[0], "backlog")) { /* backlog */
4133 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004135
4136 if (*(args[1]) == 0) {
4137 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004140 }
4141 curproxy->backlog = atol(args[1]);
4142 }
Willy Tarreau86034312006-12-29 00:10:33 +01004143 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004144 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004146
Willy Tarreau86034312006-12-29 00:10:33 +01004147 if (*(args[1]) == 0) {
4148 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004151 }
4152 curproxy->fullconn = atol(args[1]);
4153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4155 if (*(args[1]) == 0) {
4156 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004160 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4161 if (err) {
4162 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4163 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004166 }
4167 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004168 }
4169 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004170 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 if (curproxy == &defproxy) {
4172 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004176 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004177 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004178
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 if (strchr(args[1], ':') == NULL) {
4180 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004184 sk = str2sa(args[1]);
4185 if (!sk) {
4186 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
4189 }
4190 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004191 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 }
4193 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004194 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004196
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004197 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4198 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004203 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4204 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4205 err_code |= ERR_WARN;
4206
4207 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4208 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4209 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4210 }
4211 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4212 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4213 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4214 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004215 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4216 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4217 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4218 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004219 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004220 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
4224 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004227 char *rport, *raddr;
4228 short realport = 0;
4229 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004230
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004231 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004236 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238
4239 if (!*args[2]) {
4240 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4241 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004245
4246 err = invalid_char(args[1]);
4247 if (err) {
4248 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4249 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004252 }
4253
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004254 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004255 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004256
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004257 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4259 err_code |= ERR_ALERT | ERR_ABORT;
4260 goto out;
4261 }
4262
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004263 /* the servers are linked backwards first */
4264 newsrv->next = curproxy->srv;
4265 curproxy->srv = newsrv;
4266 newsrv->proxy = curproxy;
4267 newsrv->conf.file = file;
4268 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269
Simon Hormanaf514952011-06-21 14:34:57 +09004270 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004271 LIST_INIT(&newsrv->pendconns);
4272 do_check = 0;
4273 newsrv->state = SRV_RUNNING; /* early server setup */
4274 newsrv->last_change = now.tv_sec;
4275 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004277 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004278 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004279 * - IP: => port=+0, relative
4280 * - IP:N => port=N, absolute
4281 * - IP:+N => port=+N, relative
4282 * - IP:-N => port=-N, relative
4283 */
4284 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004285 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004286 if (rport) {
4287 *rport++ = 0;
4288 realport = atol(rport);
4289 if (!isdigit((unsigned char)*rport))
4290 newsrv->state |= SRV_MAPPORTS;
4291 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004293
Willy Tarreaufab5a432011-03-04 15:31:53 +01004294 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004295 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004296 if (!sk) {
4297 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004302 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004303 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004304
4305 if (!sk) {
4306 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4307 file, linenum, newsrv->addr.ss_family, args[2]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004311 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004312
4313 newsrv->check_port = curproxy->defsrv.check_port;
4314 newsrv->inter = curproxy->defsrv.inter;
4315 newsrv->fastinter = curproxy->defsrv.fastinter;
4316 newsrv->downinter = curproxy->defsrv.downinter;
4317 newsrv->rise = curproxy->defsrv.rise;
4318 newsrv->fall = curproxy->defsrv.fall;
4319 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4320 newsrv->minconn = curproxy->defsrv.minconn;
4321 newsrv->maxconn = curproxy->defsrv.maxconn;
4322 newsrv->slowstart = curproxy->defsrv.slowstart;
4323 newsrv->onerror = curproxy->defsrv.onerror;
4324 newsrv->consecutive_errors_limit
4325 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004326#ifdef OPENSSL
4327 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4328#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004329 newsrv->uweight = newsrv->iweight
4330 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004332 newsrv->curfd = -1; /* no health-check in progress */
4333 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004335 cur_arg = 3;
4336 } else {
4337 newsrv = &curproxy->defsrv;
4338 cur_arg = 1;
4339 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004340
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004342 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004343 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004344
4345 if (!*args[cur_arg + 1]) {
4346 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4347 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004350 }
4351
4352 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004353 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004354
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004355 if (newsrv->puid <= 0) {
4356 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004357 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004360 }
4361
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004362 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4363 if (node) {
4364 struct server *target = container_of(node, struct server, conf.id);
4365 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4366 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004371 cur_arg += 2;
4372 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 newsrv->cookie = strdup(args[cur_arg + 1]);
4375 newsrv->cklen = strlen(args[cur_arg + 1]);
4376 cur_arg += 2;
4377 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004378 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004379 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4380 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4381 cur_arg += 2;
4382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004384 if (!*args[cur_arg + 1]) {
4385 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4386 file, linenum, args[cur_arg]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
4390
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004392 if (newsrv->rise <= 0) {
4393 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4394 file, linenum, args[cur_arg]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398
Willy Tarreau96839092010-03-29 10:02:24 +02004399 if (newsrv->health)
4400 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 cur_arg += 2;
4402 }
4403 else if (!strcmp(args[cur_arg], "fall")) {
4404 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004405
4406 if (!*args[cur_arg + 1]) {
4407 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4408 file, linenum, args[cur_arg]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
4412
4413 if (newsrv->fall <= 0) {
4414 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4415 file, linenum, args[cur_arg]);
4416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
4418 }
4419
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 cur_arg += 2;
4421 }
4422 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004423 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4424 if (err) {
4425 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4426 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004429 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004430 if (val <= 0) {
4431 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4432 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004435 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004436 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 cur_arg += 2;
4438 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004439 else if (!strcmp(args[cur_arg], "fastinter")) {
4440 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4441 if (err) {
4442 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4443 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004446 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004447 if (val <= 0) {
4448 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4449 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004452 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004453 newsrv->fastinter = val;
4454 cur_arg += 2;
4455 }
4456 else if (!strcmp(args[cur_arg], "downinter")) {
4457 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4458 if (err) {
4459 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4460 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004463 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004464 if (val <= 0) {
4465 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4466 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004469 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004470 newsrv->downinter = val;
4471 cur_arg += 2;
4472 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004473 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004474 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004475 if (!sk) {
4476 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
4479 }
4480 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004481 cur_arg += 2;
4482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 else if (!strcmp(args[cur_arg], "port")) {
4484 newsrv->check_port = atol(args[cur_arg + 1]);
4485 cur_arg += 2;
4486 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004487 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 newsrv->state |= SRV_BACKUP;
4489 cur_arg ++;
4490 }
Simon Hormanfa461682011-06-25 09:39:49 +09004491 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4492 newsrv->state |= SRV_NON_STICK;
4493 cur_arg ++;
4494 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004495 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4496 newsrv->state |= SRV_SEND_PROXY;
4497 cur_arg ++;
4498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 else if (!strcmp(args[cur_arg], "weight")) {
4500 int w;
4501 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004502 if (w < 0 || w > 256) {
4503 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004508 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 cur_arg += 2;
4510 }
4511 else if (!strcmp(args[cur_arg], "minconn")) {
4512 newsrv->minconn = atol(args[cur_arg + 1]);
4513 cur_arg += 2;
4514 }
4515 else if (!strcmp(args[cur_arg], "maxconn")) {
4516 newsrv->maxconn = atol(args[cur_arg + 1]);
4517 cur_arg += 2;
4518 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004519 else if (!strcmp(args[cur_arg], "maxqueue")) {
4520 newsrv->maxqueue = atol(args[cur_arg + 1]);
4521 cur_arg += 2;
4522 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004523 else if (!strcmp(args[cur_arg], "slowstart")) {
4524 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004525 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004526 if (err) {
4527 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4528 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004531 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004532 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004533 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4534 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004537 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004538 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004539 cur_arg += 2;
4540 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004541 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004542
4543 if (!*args[cur_arg + 1]) {
4544 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4545 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004548 }
4549
4550 newsrv->trackit = strdup(args[cur_arg + 1]);
4551
4552 cur_arg += 2;
4553 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004554 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 global.maxsock++;
4556 do_check = 1;
4557 cur_arg += 1;
4558 }
Willy Tarreau96839092010-03-29 10:02:24 +02004559 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4560 newsrv->state |= SRV_MAINTAIN;
4561 newsrv->state &= ~SRV_RUNNING;
4562 newsrv->health = 0;
4563 cur_arg += 1;
4564 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004565 else if (!strcmp(args[cur_arg], "ssl")) {
4566#ifdef USE_OPENSSL
4567 newsrv->use_ssl = 1;
4568 cur_arg += 1;
4569#else /* USE_OPENSSL */
4570 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4571 file, linenum, args[cur_arg]);
4572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574#endif /* USE_OPENSSL */
4575 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004576 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4577#ifdef USE_OPENSSL
4578 if (!*args[cur_arg + 1]) {
4579 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4580 file, linenum, args[0], args[cur_arg]);
4581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
4583 }
4584
4585 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4586
4587 cur_arg += 2;
4588 continue;
4589#else
4590 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4591 file, linenum, args[0], args[cur_arg]);
4592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594#endif
4595 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004596 else if (!strcmp(args[cur_arg], "nosslv3")) {
4597#ifdef USE_OPENSSL
4598 newsrv->ssl_ctx.nosslv3 = 1;
4599 cur_arg += 1;
4600#else /* USE_OPENSSL */
4601 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4602 file, linenum, args[cur_arg]);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605#endif /* USE_OPENSSL */
4606 }
4607 else if (!strcmp(args[cur_arg], "notlsv1")) {
4608#ifdef USE_OPENSSL
4609 newsrv->ssl_ctx.notlsv1 = 1;
4610 cur_arg += 1;
4611#else /* USE_OPENSSL */
4612 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4613 file, linenum, args[cur_arg]);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616#endif /* USE_OPENSSL */
4617 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004618 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004619 if (!strcmp(args[cur_arg + 1], "none"))
4620 newsrv->observe = HANA_OBS_NONE;
4621 else if (!strcmp(args[cur_arg + 1], "layer4"))
4622 newsrv->observe = HANA_OBS_LAYER4;
4623 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4624 if (curproxy->mode != PR_MODE_HTTP) {
4625 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4626 file, linenum, args[cur_arg + 1]);
4627 err_code |= ERR_ALERT;
4628 }
4629 newsrv->observe = HANA_OBS_LAYER7;
4630 }
4631 else {
4632 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004633 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004634 file, linenum, args[cur_arg], args[cur_arg + 1]);
4635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
4637 }
4638
4639 cur_arg += 2;
4640 }
4641 else if (!strcmp(args[cur_arg], "on-error")) {
4642 if (!strcmp(args[cur_arg + 1], "fastinter"))
4643 newsrv->onerror = HANA_ONERR_FASTINTER;
4644 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4645 newsrv->onerror = HANA_ONERR_FAILCHK;
4646 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4647 newsrv->onerror = HANA_ONERR_SUDDTH;
4648 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4649 newsrv->onerror = HANA_ONERR_MARKDWN;
4650 else {
4651 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004652 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004653 file, linenum, args[cur_arg], args[cur_arg + 1]);
4654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
4656 }
4657
4658 cur_arg += 2;
4659 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004660 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4661 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4662 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4663 else {
4664 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4665 file, linenum, args[cur_arg], args[cur_arg + 1]);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669
4670 cur_arg += 2;
4671 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004672 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4673 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4674 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4675 else {
4676 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4677 file, linenum, args[cur_arg], args[cur_arg + 1]);
4678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
4680 }
4681
4682 cur_arg += 2;
4683 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004684 else if (!strcmp(args[cur_arg], "error-limit")) {
4685 if (!*args[cur_arg + 1]) {
4686 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4687 file, linenum, args[cur_arg]);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
4691
4692 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4693
4694 if (newsrv->consecutive_errors_limit <= 0) {
4695 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4696 file, linenum, args[cur_arg]);
4697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004700 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004701 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004702 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004703 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004704 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004705
Willy Tarreaubaaee002006-06-26 02:48:02 +02004706 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004707#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004708 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004709 file, linenum, "source", "usesrc");
4710#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004711 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004713#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 }
4717 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004718 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4719 if (!sk) {
4720 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 }
4724 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004725
4726 if (port_low != port_high) {
4727 int i;
4728 if (port_low <= 0 || port_low > 65535 ||
4729 port_high <= 0 || port_high > 65535 ||
4730 port_low > port_high) {
4731 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4732 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004735 }
4736 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4737 for (i = 0; i < newsrv->sport_range->size; i++)
4738 newsrv->sport_range->ports[i] = port_low + i;
4739 }
4740
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004742 while (*(args[cur_arg])) {
4743 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004744#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4745#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004746 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4747 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4748 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004751 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004752#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004753 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004754 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004755 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004758 }
4759 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004760 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004761 newsrv->state |= SRV_TPROXY_CLI;
4762 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004763 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004764 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004765 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4766 char *name, *end;
4767
4768 name = args[cur_arg+1] + 7;
4769 while (isspace(*name))
4770 name++;
4771
4772 end = name;
4773 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4774 end++;
4775
4776 newsrv->state &= ~SRV_TPROXY_MASK;
4777 newsrv->state |= SRV_TPROXY_DYN;
4778 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4779 newsrv->bind_hdr_len = end - name;
4780 memcpy(newsrv->bind_hdr_name, name, end - name);
4781 newsrv->bind_hdr_name[end-name] = '\0';
4782 newsrv->bind_hdr_occ = -1;
4783
4784 /* now look for an occurrence number */
4785 while (isspace(*end))
4786 end++;
4787 if (*end == ',') {
4788 end++;
4789 name = end;
4790 if (*end == '-')
4791 end++;
4792 while (isdigit(*end))
4793 end++;
4794 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4795 }
4796
4797 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4798 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4799 " occurrences values smaller than %d.\n",
4800 file, linenum, MAX_HDR_HISTORY);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004804 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004805 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004806 if (!sk) {
4807 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
4811 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004812 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004813 }
4814 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004815#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004816 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004817#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004818 cur_arg += 2;
4819 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004820#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004821 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004822 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004825#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4826 } /* "usesrc" */
4827
4828 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4829#ifdef SO_BINDTODEVICE
4830 if (!*args[cur_arg + 1]) {
4831 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4832 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004835 }
4836 if (newsrv->iface_name)
4837 free(newsrv->iface_name);
4838
4839 newsrv->iface_name = strdup(args[cur_arg + 1]);
4840 newsrv->iface_len = strlen(newsrv->iface_name);
4841 global.last_checks |= LSTCHK_NETADM;
4842#else
4843 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4844 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004847#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004848 cur_arg += 2;
4849 continue;
4850 }
4851 /* this keyword in not an option of "source" */
4852 break;
4853 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004855 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004856 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4857 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004862 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004863 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 +01004864 file, linenum, newsrv->id);
4865 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004866 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 +01004867 file, linenum);
4868
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
4872 }
4873
4874 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004875 if (newsrv->trackit) {
4876 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4877 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004880 }
4881
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004882 /* try to get the port from check_addr if check_port not set */
4883 if (!newsrv->check_port)
4884 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004885
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4887 newsrv->check_port = realport; /* by default */
4888 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004889 /* not yet valid, because no port was set on
4890 * the server either. We'll check if we have
4891 * a known port on the first listener.
4892 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004893 struct listener *l = curproxy->listen;
4894 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4895 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004896 }
4897 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4899 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004903
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004904 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004905 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004906 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4907 err_code |= ERR_ALERT | ERR_ABORT;
4908 goto out;
4909 }
4910
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004911 /* Allocate buffer for partial check results... */
4912 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4913 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4914 err_code |= ERR_ALERT | ERR_ABORT;
4915 goto out;
4916 }
4917
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004918 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 newsrv->state |= SRV_CHECKED;
4920 }
4921
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004922 if (!defsrv) {
4923 if (newsrv->state & SRV_BACKUP)
4924 curproxy->srv_bck++;
4925 else
4926 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004927
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004928 newsrv->prev_state = newsrv->state;
4929 }
William Lallemanda73203e2012-03-12 12:48:57 +01004930 }
4931
4932 else if (strcmp(args[0], "unique-id-format") == 0) {
4933 if (!*(args[1])) {
4934 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
4937 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004938 free(curproxy->uniqueid_format_string);
4939 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004940 }
William Lallemanda73203e2012-03-12 12:48:57 +01004941
4942 else if (strcmp(args[0], "unique-id-header") == 0) {
4943 if (!*(args[1])) {
4944 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
4948 free(curproxy->header_unique_id);
4949 curproxy->header_unique_id = strdup(args[1]);
4950 }
4951
William Lallemand723b73a2012-02-08 16:37:49 +01004952 else if (strcmp(args[0], "log-format") == 0) {
4953 if (!*(args[1])) {
4954 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004958
4959 if (curproxy->logformat_string != default_http_log_format &&
4960 curproxy->logformat_string != default_tcp_log_format &&
4961 curproxy->logformat_string != clf_http_log_format)
4962 free(curproxy->logformat_string);
4963 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
William Lallemand723b73a2012-02-08 16:37:49 +01004965
William Lallemand0f99e342011-10-12 17:50:54 +02004966 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4967 /* delete previous herited or defined syslog servers */
4968 struct logsrv *back;
4969
4970 if (*(args[1]) != 0) {
4971 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975
William Lallemand723b73a2012-02-08 16:37:49 +01004976 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4977 LIST_DEL(&tmplogsrv->list);
4978 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004979 }
4980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004982 struct logsrv *logsrv;
4983
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004985 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004986 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004987 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004988 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004989 LIST_INIT(&node->list);
4990 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 }
4993 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004994
4995 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996
William Lallemand0f99e342011-10-12 17:50:54 +02004997 logsrv->facility = get_log_facility(args[2]);
4998 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
5002
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004
William Lallemand0f99e342011-10-12 17:50:54 +02005005 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005007 logsrv->level = get_log_level(args[3]);
5008 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 }
5014 }
5015
William Lallemand0f99e342011-10-12 17:50:54 +02005016 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005017 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005018 logsrv->minlvl = get_log_level(args[4]);
5019 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005020 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005024 }
5025 }
5026
Robert Tsai81ae1952007-12-05 10:47:29 +01005027 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01005028 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005029 if (!sk) {
5030 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01005031 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
William Lallemand0f99e342011-10-12 17:50:54 +02005035 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01005036 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005037 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01005038 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01005039 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
William Lallemand0f99e342011-10-12 17:50:54 +02005043 logsrv->addr = *sk;
5044 if (!get_host_port(&logsrv->addr))
5045 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
William Lallemand0f99e342011-10-12 17:50:54 +02005047
5048 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
5050 else {
5051 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5052 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
5056 }
5057 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005058 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005059 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060
Willy Tarreau977b8e42006-12-29 14:19:17 +01005061 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005063
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5066 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005070
5071 /* we must first clear any optional default setting */
5072 curproxy->options &= ~PR_O_TPXY_MASK;
5073 free(curproxy->iface_name);
5074 curproxy->iface_name = NULL;
5075 curproxy->iface_len = 0;
5076
Willy Tarreaud5191e72010-02-09 20:50:45 +01005077 sk = str2sa(args[1]);
5078 if (!sk) {
5079 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
5083 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005085
5086 cur_arg = 2;
5087 while (*(args[cur_arg])) {
5088 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005089#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5090#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005091 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5092 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5093 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005096 }
5097#endif
5098 if (!*args[cur_arg + 1]) {
5099 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5100 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005103 }
5104
5105 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005106 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 curproxy->options |= PR_O_TPXY_CLI;
5108 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005109 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005110 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005111 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5112 char *name, *end;
5113
5114 name = args[cur_arg+1] + 7;
5115 while (isspace(*name))
5116 name++;
5117
5118 end = name;
5119 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5120 end++;
5121
5122 curproxy->options &= ~PR_O_TPXY_MASK;
5123 curproxy->options |= PR_O_TPXY_DYN;
5124 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5125 curproxy->bind_hdr_len = end - name;
5126 memcpy(curproxy->bind_hdr_name, name, end - name);
5127 curproxy->bind_hdr_name[end-name] = '\0';
5128 curproxy->bind_hdr_occ = -1;
5129
5130 /* now look for an occurrence number */
5131 while (isspace(*end))
5132 end++;
5133 if (*end == ',') {
5134 end++;
5135 name = end;
5136 if (*end == '-')
5137 end++;
5138 while (isdigit(*end))
5139 end++;
5140 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5141 }
5142
5143 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5144 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5145 " occurrences values smaller than %d.\n",
5146 file, linenum, MAX_HDR_HISTORY);
5147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005150 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005151 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005152 if (!sk) {
5153 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
5156 }
5157 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005158 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005159 }
5160 global.last_checks |= LSTCHK_NETADM;
5161#if !defined(CONFIG_HAP_LINUX_TPROXY)
5162 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005163#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005164#else /* no TPROXY support */
5165 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005166 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005169#endif
5170 cur_arg += 2;
5171 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005172 }
5173
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005174 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5175#ifdef SO_BINDTODEVICE
5176 if (!*args[cur_arg + 1]) {
5177 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5178 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005181 }
5182 if (curproxy->iface_name)
5183 free(curproxy->iface_name);
5184
5185 curproxy->iface_name = strdup(args[cur_arg + 1]);
5186 curproxy->iface_len = strlen(curproxy->iface_name);
5187 global.last_checks |= LSTCHK_NETADM;
5188#else
5189 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5190 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005193#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005194 cur_arg += 2;
5195 continue;
5196 }
5197 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5198 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005203 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5204 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5205 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005215 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216
5217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005218 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005219 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
5223 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005224 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005225 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005226 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
5230 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005232 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005233 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005234 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 }
5237 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005239 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005240 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
5244 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005246 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005247 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005251 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005253 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005254 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005256 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005257 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005258 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005260 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005261 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005263 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005264 }
5265 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005267 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005268 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005270 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5275 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279
5280 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005281 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005282 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
5286 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005288 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005289 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005295 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005296 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005302 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005303 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
5307 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005309 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005310 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005314 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005316 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005317 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005319 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005322 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if (curproxy == &defproxy) {
5325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005329 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 if (*(args[1]) == 0) {
5333 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005337
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005338 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005339 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5340 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5341 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5346 }
5347 else if (*args[2]) {
5348 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5349 file, linenum, args[0], args[2]);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
5353
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005354 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005355 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005356 wl->s = strdup(args[1]);
5357 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005358 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 }
5360 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5363 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005367
Willy Tarreauade5ec42010-01-28 19:33:49 +01005368 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005369 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005370 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005371 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 }
5374 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005375 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005376 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005377 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005378 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
5381 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005382 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005383 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005384 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005385 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 }
5388 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005389 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 }
5395
Willy Tarreauade5ec42010-01-28 19:33:49 +01005396 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005397 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005398 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005399 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
5402 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005403 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005404 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005405 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005406 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 }
5409 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005410 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005411 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005412 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005413 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 }
5416 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005417 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005418
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 if (curproxy == &defproxy) {
5420 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005424 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005425 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 if (*(args[1]) == 0) {
5428 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
5432
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005433 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005434 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5435 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5436 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005437 err_code |= ERR_ALERT | ERR_FATAL;
5438 goto out;
5439 }
5440 err_code |= warnif_cond_requires_req(cond, file, linenum);
5441 }
5442 else if (*args[2]) {
5443 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5444 file, linenum, args[0], args[2]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
5448
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005449 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005450 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005451 wl->s = strdup(args[1]);
5452 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
5454 else if (!strcmp(args[0], "errorloc") ||
5455 !strcmp(args[0], "errorloc302") ||
5456 !strcmp(args[0], "errorloc303")) { /* error location */
5457 int errnum, errlen;
5458 char *err;
5459
Willy Tarreau977b8e42006-12-29 14:19:17 +01005460 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005462
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005464 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 }
5468
5469 errnum = atol(args[1]);
5470 if (!strcmp(args[0], "errorloc303")) {
5471 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5472 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5473 } else {
5474 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5475 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5476 }
5477
Willy Tarreau0f772532006-12-23 20:51:41 +01005478 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5479 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005480 chunk_destroy(&curproxy->errmsg[rc]);
5481 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005482 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005485
5486 if (rc >= HTTP_ERR_SIZE) {
5487 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5488 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 free(err);
5490 }
5491 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005492 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5493 int errnum, errlen, fd;
5494 char *err;
5495 struct stat stat;
5496
5497 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005499
5500 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005501 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005504 }
5505
5506 fd = open(args[2], O_RDONLY);
5507 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5508 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5509 file, linenum, args[2], args[1]);
5510 if (fd >= 0)
5511 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005514 }
5515
Willy Tarreau27a674e2009-08-17 07:23:33 +02005516 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005517 errlen = stat.st_size;
5518 } else {
5519 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005520 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005521 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005522 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005523 }
5524
5525 err = malloc(errlen); /* malloc() must succeed during parsing */
5526 errnum = read(fd, err, errlen);
5527 if (errnum != errlen) {
5528 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5529 file, linenum, args[2], args[1]);
5530 close(fd);
5531 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005534 }
5535 close(fd);
5536
5537 errnum = atol(args[1]);
5538 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5539 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005540 chunk_destroy(&curproxy->errmsg[rc]);
5541 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005542 break;
5543 }
5544 }
5545
5546 if (rc >= HTTP_ERR_SIZE) {
5547 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5548 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005549 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005550 free(err);
5551 }
5552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005554 struct cfg_kw_list *kwl;
5555 int index;
5556
5557 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5558 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5559 if (kwl->kw[index].section != CFG_LISTEN)
5560 continue;
5561 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5562 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005563 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005564 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005565 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005566 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005567 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005570 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005571 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005572 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_WARN;
5574 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005575 }
Willy Tarreau93893792009-07-23 13:19:11 +02005576 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005577 }
5578 }
5579 }
5580
Willy Tarreau6daf3432008-01-22 16:44:08 +01005581 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
Willy Tarreau93893792009-07-23 13:19:11 +02005585 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005586 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588}
5589
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005590int
5591cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5592{
5593
5594 int err_code = 0;
5595 const char *err;
5596
5597 if (!strcmp(args[0], "userlist")) { /* new userlist */
5598 struct userlist *newul;
5599
5600 if (!*args[1]) {
5601 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5602 file, linenum, args[0]);
5603 err_code |= ERR_ALERT | ERR_FATAL;
5604 goto out;
5605 }
5606
5607 err = invalid_char(args[1]);
5608 if (err) {
5609 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5610 file, linenum, *err, args[0], args[1]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614
5615 for (newul = userlist; newul; newul = newul->next)
5616 if (!strcmp(newul->name, args[1])) {
5617 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5618 file, linenum, args[1]);
5619 err_code |= ERR_WARN;
5620 goto out;
5621 }
5622
5623 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5624 if (!newul) {
5625 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5626 err_code |= ERR_ALERT | ERR_ABORT;
5627 goto out;
5628 }
5629
5630 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5631 newul->name = strdup(args[1]);
5632
5633 if (!newul->groupusers | !newul->name) {
5634 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5635 err_code |= ERR_ALERT | ERR_ABORT;
5636 goto out;
5637 }
5638
5639 newul->next = userlist;
5640 userlist = newul;
5641
5642 } else if (!strcmp(args[0], "group")) { /* new group */
5643 int cur_arg, i;
5644 const char *err;
5645
5646 if (!*args[1]) {
5647 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5648 file, linenum, args[0]);
5649 err_code |= ERR_ALERT | ERR_FATAL;
5650 goto out;
5651 }
5652
5653 err = invalid_char(args[1]);
5654 if (err) {
5655 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5656 file, linenum, *err, args[0], args[1]);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660
5661 for(i = 0; i < userlist->grpcnt; i++)
5662 if (!strcmp(userlist->groups[i], args[1])) {
5663 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5664 file, linenum, args[1], userlist->name);
5665 err_code |= ERR_ALERT;
5666 goto out;
5667 }
5668
5669 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5670 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5671 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
5674 }
5675
5676 cur_arg = 2;
5677
5678 while (*args[cur_arg]) {
5679 if (!strcmp(args[cur_arg], "users")) {
5680 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5681 cur_arg += 2;
5682 continue;
5683 } else {
5684 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5685 file, linenum, args[0]);
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
5689 }
5690
5691 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5692 } else if (!strcmp(args[0], "user")) { /* new user */
5693 struct auth_users *newuser;
5694 int cur_arg;
5695
5696 if (!*args[1]) {
5697 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5698 file, linenum, args[0]);
5699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
5702
5703 for (newuser = userlist->users; newuser; newuser = newuser->next)
5704 if (!strcmp(newuser->user, args[1])) {
5705 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5706 file, linenum, args[1], userlist->name);
5707 err_code |= ERR_ALERT;
5708 goto out;
5709 }
5710
5711 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5712 if (!newuser) {
5713 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5714 err_code |= ERR_ALERT | ERR_ABORT;
5715 goto out;
5716 }
5717
5718 newuser->user = strdup(args[1]);
5719
5720 newuser->next = userlist->users;
5721 userlist->users = newuser;
5722
5723 cur_arg = 2;
5724
5725 while (*args[cur_arg]) {
5726 if (!strcmp(args[cur_arg], "password")) {
5727#ifndef CONFIG_HAP_CRYPT
5728 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5729 file, linenum);
5730 err_code |= ERR_ALERT;
5731#endif
5732 newuser->pass = strdup(args[cur_arg + 1]);
5733 cur_arg += 2;
5734 continue;
5735 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5736 newuser->pass = strdup(args[cur_arg + 1]);
5737 newuser->flags |= AU_O_INSECURE;
5738 cur_arg += 2;
5739 continue;
5740 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005741 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005742 cur_arg += 2;
5743 continue;
5744 } else {
5745 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5746 file, linenum, args[0]);
5747 err_code |= ERR_ALERT | ERR_FATAL;
5748 goto out;
5749 }
5750 }
5751 } else {
5752 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5753 err_code |= ERR_ALERT | ERR_FATAL;
5754 }
5755
5756out:
5757 return err_code;
5758}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759
5760/*
5761 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005762 * Returns the error code, 0 if OK, or any combination of :
5763 * - ERR_ABORT: must abort ASAP
5764 * - ERR_FATAL: we can continue parsing but not start the service
5765 * - ERR_WARN: a warning has been emitted
5766 * - ERR_ALERT: an alert has been emitted
5767 * Only the two first ones can stop processing, the two others are just
5768 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005770int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005772 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 FILE *f;
5774 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005776 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 if ((f=fopen(file,"r")) == NULL)
5779 return -1;
5780
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005781 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005782 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005783 char *end;
5784 char *args[MAX_LINE_ARGS + 1];
5785 char *line = thisline;
5786
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 linenum++;
5788
5789 end = line + strlen(line);
5790
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005791 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5792 /* Check if we reached the limit and the last char is not \n.
5793 * Watch out for the last line without the terminating '\n'!
5794 */
5795 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005796 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005798 }
5799
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005801 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 line++;
5803
5804 arg = 0;
5805 args[arg] = line;
5806
5807 while (*line && arg < MAX_LINE_ARGS) {
5808 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5809 * C equivalent value. Other combinations left unchanged (eg: \1).
5810 */
5811 if (*line == '\\') {
5812 int skip = 0;
5813 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5814 *line = line[1];
5815 skip = 1;
5816 }
5817 else if (line[1] == 'r') {
5818 *line = '\r';
5819 skip = 1;
5820 }
5821 else if (line[1] == 'n') {
5822 *line = '\n';
5823 skip = 1;
5824 }
5825 else if (line[1] == 't') {
5826 *line = '\t';
5827 skip = 1;
5828 }
5829 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005830 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 unsigned char hex1, hex2;
5832 hex1 = toupper(line[2]) - '0';
5833 hex2 = toupper(line[3]) - '0';
5834 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5835 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5836 *line = (hex1<<4) + hex2;
5837 skip = 3;
5838 }
5839 else {
5840 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005841 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
5843 }
5844 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005845 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 end -= skip;
5847 }
5848 line++;
5849 }
5850 else if (*line == '#' || *line == '\n' || *line == '\r') {
5851 /* end of string, end of loop */
5852 *line = 0;
5853 break;
5854 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005855 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005857 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005858 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 line++;
5860 args[++arg] = line;
5861 }
5862 else {
5863 line++;
5864 }
5865 }
5866
5867 /* empty line */
5868 if (!**args)
5869 continue;
5870
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005871 if (*line) {
5872 /* we had to stop due to too many args.
5873 * Let's terminate the string, print the offending part then cut the
5874 * last arg.
5875 */
5876 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5877 line++;
5878 *line = '\0';
5879
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005880 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005881 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 args[arg] = line;
5884 }
5885
Willy Tarreau540abe42007-05-02 20:50:16 +02005886 /* zero out remaining args and ensure that at least one entry
5887 * is zeroed out.
5888 */
5889 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890 args[arg] = line;
5891 }
5892
Willy Tarreau3842f002009-06-14 11:39:52 +02005893 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005894 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005895 char *tmp;
5896
Willy Tarreau3842f002009-06-14 11:39:52 +02005897 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005898 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005899 for (arg=0; *args[arg+1]; arg++)
5900 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005901 *tmp = '\0'; // fix the next arg to \0
5902 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005903 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005904 else if (!strcmp(args[0], "default")) {
5905 kwm = KWM_DEF;
5906 for (arg=0; *args[arg+1]; arg++)
5907 args[arg] = args[arg+1]; // shift args after inversion
5908 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005909
William Lallemand0f99e342011-10-12 17:50:54 +02005910 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5911 strcmp(args[0], "log") != 0) {
5912 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005914 }
5915
Willy Tarreau977b8e42006-12-29 14:19:17 +01005916 if (!strcmp(args[0], "listen") ||
5917 !strcmp(args[0], "frontend") ||
5918 !strcmp(args[0], "backend") ||
5919 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005920 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005922 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005923 cursection = strdup(args[0]);
5924 }
5925 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005927 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005928 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005929 }
5930 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005931 confsect = CFG_USERLIST;
5932 free(cursection);
5933 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005934 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005935 else if (!strcmp(args[0], "peers")) {
5936 confsect = CFG_PEERS;
5937 free(cursection);
5938 cursection = strdup(args[0]);
5939 }
5940
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 /* else it's a section keyword */
5942
5943 switch (confsect) {
5944 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005945 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005946 break;
5947 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005948 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005950 case CFG_USERLIST:
5951 err_code |= cfg_parse_users(file, linenum, args, kwm);
5952 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005953 case CFG_PEERS:
5954 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5955 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005956 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005957 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005960
5961 if (err_code & ERR_ABORT)
5962 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005964 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005965 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005967 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005968}
5969
Willy Tarreaubb925012009-07-23 13:36:36 +02005970/*
5971 * Returns the error code, 0 if OK, or any combination of :
5972 * - ERR_ABORT: must abort ASAP
5973 * - ERR_FATAL: we can continue parsing but not start the service
5974 * - ERR_WARN: a warning has been emitted
5975 * - ERR_ALERT: an alert has been emitted
5976 * Only the two first ones can stop processing, the two others are just
5977 * indicators.
5978 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979int check_config_validity()
5980{
5981 int cfgerr = 0;
5982 struct proxy *curproxy = NULL;
5983 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005984 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005985 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005986 unsigned int next_pxid = 1;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02005987 struct ssl_conf *ssl_conf, *ssl_back;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02005989 ssl_back = ssl_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 /*
5991 * Now, check for the integrity of all that we have collected.
5992 */
5993
5994 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005995 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005997 /* first, we will invert the proxy list order */
5998 curproxy = NULL;
5999 while (proxy) {
6000 struct proxy *next;
6001
6002 next = proxy->next;
6003 proxy->next = curproxy;
6004 curproxy = proxy;
6005 if (!next)
6006 break;
6007 proxy = next;
6008 }
6009
Willy Tarreaubaaee002006-06-26 02:48:02 +02006010 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006011 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006012 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006013 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006014 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006015 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006016 unsigned int next_id;
6017
6018 if (!curproxy->uuid) {
6019 /* proxy ID not set, use automatic numbering with first
6020 * spare entry starting with next_pxid.
6021 */
6022 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6023 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6024 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006025 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006026 next_pxid++;
6027
Willy Tarreau55ea7572007-06-17 19:56:27 +02006028
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006030 /* ensure we don't keep listeners uselessly bound */
6031 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006032 curproxy = curproxy->next;
6033 continue;
6034 }
6035
Willy Tarreauff01a212009-03-15 13:46:16 +01006036 switch (curproxy->mode) {
6037 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006038 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006039 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006040 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6041 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006042 cfgerr++;
6043 }
6044
6045 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006046 Warning("config : servers will be ignored for %s '%s'.\n",
6047 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006048 break;
6049
6050 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006051 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006052 break;
6053
6054 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006055 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006056 break;
6057 }
6058
6059 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006060 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
6061 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 cfgerr++;
6063 }
Willy Tarreauff01a212009-03-15 13:46:16 +01006064
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006065 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006066 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006067 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006068 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6069 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006070 cfgerr++;
6071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006073 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006074 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6075 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006076 cfgerr++;
6077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006079 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006080 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6081 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006082 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006083 }
6084 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006085 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006086 /* If no LB algo is set in a backend, and we're not in
6087 * transparent mode, dispatch mode nor proxy mode, we
6088 * want to use balance roundrobin by default.
6089 */
6090 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6091 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006092 }
6093 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006094
Willy Tarreau1620ec32011-08-06 17:05:02 +02006095 if (curproxy->options & PR_O_DISPATCH)
6096 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6097 else if (curproxy->options & PR_O_HTTP_PROXY)
6098 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6099 else if (curproxy->options & PR_O_TRANSP)
6100 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006101
Willy Tarreau1620ec32011-08-06 17:05:02 +02006102 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6103 if (curproxy->options & PR_O_DISABLE404) {
6104 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6105 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6106 err_code |= ERR_WARN;
6107 curproxy->options &= ~PR_O_DISABLE404;
6108 }
6109 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6110 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6111 "send-state", proxy_type_str(curproxy), curproxy->id);
6112 err_code |= ERR_WARN;
6113 curproxy->options &= ~PR_O2_CHK_SNDST;
6114 }
Willy Tarreauef781042010-01-27 11:53:01 +01006115 }
6116
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006117 /* if a default backend was specified, let's find it */
6118 if (curproxy->defbe.name) {
6119 struct proxy *target;
6120
Alex Williams96532db2009-11-01 21:27:13 -05006121 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006122 if (!target) {
6123 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6124 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006125 cfgerr++;
6126 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006127 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6128 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006129 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006130 } else {
6131 free(curproxy->defbe.name);
6132 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006133 /* we force the backend to be present on at least all of
6134 * the frontend's processes.
6135 */
6136 target->bind_proc = curproxy->bind_proc ?
6137 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006138
6139 /* Emit a warning if this proxy also has some servers */
6140 if (curproxy->srv) {
6141 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6142 curproxy->id);
6143 err_code |= ERR_WARN;
6144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145 }
6146 }
6147
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006148 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006149 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6150 /* map jump target for ACT_SETBE in req_rep chain */
6151 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006152 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006153 struct proxy *target;
6154
Willy Tarreaua496b602006-12-17 23:15:24 +01006155 if (exp->action != ACT_SETBE)
6156 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006157
Alex Williams96532db2009-11-01 21:27:13 -05006158 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006159 if (!target) {
6160 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6161 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006162 cfgerr++;
6163 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006164 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6165 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006166 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006167 } else {
6168 free((void *)exp->replace);
6169 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006170 /* we force the backend to be present on at least all of
6171 * the frontend's processes.
6172 */
6173 target->bind_proc = curproxy->bind_proc ?
6174 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006175 }
6176 }
6177 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006178
6179 /* find the target proxy for 'use_backend' rules */
6180 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006181 struct proxy *target;
6182
Alex Williams96532db2009-11-01 21:27:13 -05006183 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006184
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006185 if (!target) {
6186 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6187 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006188 cfgerr++;
6189 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006190 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6191 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006192 cfgerr++;
6193 } else {
6194 free((void *)rule->be.name);
6195 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006196 /* we force the backend to be present on at least all of
6197 * the frontend's processes.
6198 */
6199 target->bind_proc = curproxy->bind_proc ?
6200 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006201 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006202 }
6203
6204 /* find the target proxy for 'use_backend' rules */
6205 list_for_each_entry(srule, &curproxy->server_rules, list) {
6206 struct server *target = findserver(curproxy, srule->srv.name);
6207
6208 if (!target) {
6209 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6210 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6211 cfgerr++;
6212 continue;
6213 }
6214 free((void *)srule->srv.name);
6215 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006216 }
6217
Emeric Brunb982a3d2010-01-04 15:45:53 +01006218 /* find the target table for 'stick' rules */
6219 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6220 struct proxy *target;
6221
Emeric Brun1d33b292010-01-04 15:47:17 +01006222 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6223 if (mrule->flags & STK_IS_STORE)
6224 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6225
Emeric Brunb982a3d2010-01-04 15:45:53 +01006226 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006227 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006228 else
6229 target = curproxy;
6230
6231 if (!target) {
6232 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6233 curproxy->id, mrule->table.name);
6234 cfgerr++;
6235 }
6236 else if (target->table.size == 0) {
6237 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6238 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6239 cfgerr++;
6240 }
Willy Tarreau12785782012-04-27 21:37:17 +02006241 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6242 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006243 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6244 cfgerr++;
6245 }
6246 else {
6247 free((void *)mrule->table.name);
6248 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006249 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006250 }
6251 }
6252
6253 /* find the target table for 'store response' rules */
6254 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6255 struct proxy *target;
6256
Emeric Brun1d33b292010-01-04 15:47:17 +01006257 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6258
Emeric Brunb982a3d2010-01-04 15:45:53 +01006259 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006260 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006261 else
6262 target = curproxy;
6263
6264 if (!target) {
6265 Alert("Proxy '%s': unable to find store table '%s'.\n",
6266 curproxy->id, mrule->table.name);
6267 cfgerr++;
6268 }
6269 else if (target->table.size == 0) {
6270 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6271 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6272 cfgerr++;
6273 }
Willy Tarreau12785782012-04-27 21:37:17 +02006274 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6275 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006276 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6277 cfgerr++;
6278 }
6279 else {
6280 free((void *)mrule->table.name);
6281 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006282 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006283 }
6284 }
6285
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006286 /* find the target table for 'tcp-request' layer 4 rules */
6287 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6288 struct proxy *target;
6289
Willy Tarreau56123282010-08-06 19:06:56 +02006290 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006291 continue;
6292
6293 if (trule->act_prm.trk_ctr.table.n)
6294 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6295 else
6296 target = curproxy;
6297
6298 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006299 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6300 curproxy->id, trule->act_prm.trk_ctr.table.n,
6301 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006302 cfgerr++;
6303 }
6304 else if (target->table.size == 0) {
6305 Alert("Proxy '%s': table '%s' used but not configured.\n",
6306 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6307 cfgerr++;
6308 }
6309 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006310 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 +02006311 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6312 cfgerr++;
6313 }
6314 else {
6315 free(trule->act_prm.trk_ctr.table.n);
6316 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006317 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006318 * to pass a list of counters to track and allocate them right here using
6319 * stktable_alloc_data_type().
6320 */
6321 }
6322 }
6323
Willy Tarreaud1f96522010-08-03 19:34:32 +02006324 /* find the target table for 'tcp-request' layer 6 rules */
6325 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6326 struct proxy *target;
6327
Willy Tarreau56123282010-08-06 19:06:56 +02006328 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006329 continue;
6330
6331 if (trule->act_prm.trk_ctr.table.n)
6332 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6333 else
6334 target = curproxy;
6335
6336 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006337 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6338 curproxy->id, trule->act_prm.trk_ctr.table.n,
6339 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006340 cfgerr++;
6341 }
6342 else if (target->table.size == 0) {
6343 Alert("Proxy '%s': table '%s' used but not configured.\n",
6344 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6345 cfgerr++;
6346 }
6347 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006348 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 +02006349 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6350 cfgerr++;
6351 }
6352 else {
6353 free(trule->act_prm.trk_ctr.table.n);
6354 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006355 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006356 * to pass a list of counters to track and allocate them right here using
6357 * stktable_alloc_data_type().
6358 */
6359 }
6360 }
6361
Emeric Brun32da3c42010-09-23 18:39:19 +02006362 if (curproxy->table.peers.name) {
6363 struct peers *curpeers = peers;
6364
6365 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6366 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6367 free((void *)curproxy->table.peers.name);
6368 curproxy->table.peers.p = peers;
6369 break;
6370 }
6371 }
6372
6373 if (!curpeers) {
6374 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6375 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006376 free((void *)curproxy->table.peers.name);
6377 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006378 cfgerr++;
6379 }
6380 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006381 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6382 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006383 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006384 cfgerr++;
6385 }
6386 }
6387
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006388 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006389 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006390 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6391 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6392 "proxy", curproxy->id);
6393 cfgerr++;
6394 goto out_uri_auth_compat;
6395 }
6396
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006397 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006398 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006399 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006400 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006401
Willy Tarreau95fa4692010-02-01 13:05:50 +01006402 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6403 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006404
6405 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006406 uri_auth_compat_req[i++] = "realm";
6407 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6408 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006409
Willy Tarreau95fa4692010-02-01 13:05:50 +01006410 uri_auth_compat_req[i++] = "unless";
6411 uri_auth_compat_req[i++] = "{";
6412 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6413 uri_auth_compat_req[i++] = "}";
6414 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006415
Willy Tarreauff011f22011-01-06 17:51:27 +01006416 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6417 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006418 cfgerr++;
6419 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006420 }
6421
Willy Tarreauff011f22011-01-06 17:51:27 +01006422 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006423
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006424 if (curproxy->uri_auth->auth_realm) {
6425 free(curproxy->uri_auth->auth_realm);
6426 curproxy->uri_auth->auth_realm = NULL;
6427 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006428
6429 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006430 }
6431out_uri_auth_compat:
6432
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006433 cfgerr += acl_find_targets(curproxy);
6434
Willy Tarreau2738a142006-07-08 17:28:09 +02006435 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006436 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006437 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006438 (!curproxy->timeout.connect ||
6439 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006440 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006441 " | While not properly invalid, you will certainly encounter various problems\n"
6442 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006443 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006445 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006446 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006447
Willy Tarreau1fa31262007-12-03 00:36:16 +01006448 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6449 * We must still support older configurations, so let's find out whether those
6450 * parameters have been set or must be copied from contimeouts.
6451 */
6452 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006453 if (!curproxy->timeout.tarpit ||
6454 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006455 /* tarpit timeout not set. We search in the following order:
6456 * default.tarpit, curr.connect, default.connect.
6457 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006458 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006459 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006460 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006461 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006462 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006463 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006464 }
6465 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006466 (!curproxy->timeout.queue ||
6467 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006468 /* queue timeout not set. We search in the following order:
6469 * default.queue, curr.connect, default.connect.
6470 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006471 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006472 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006473 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006474 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006475 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006476 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006477 }
6478 }
6479
Willy Tarreau1620ec32011-08-06 17:05:02 +02006480 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006481 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6482 curproxy->check_req = (char *)malloc(curproxy->check_len);
6483 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006484 }
6485
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006486 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006487 if (curproxy->nb_req_cap) {
6488 if (curproxy->mode == PR_MODE_HTTP) {
6489 curproxy->req_cap_pool = create_pool("ptrcap",
6490 curproxy->nb_req_cap * sizeof(char *),
6491 MEM_F_SHARED);
6492 } else {
6493 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6494 proxy_type_str(curproxy), curproxy->id);
6495 err_code |= ERR_WARN;
6496 curproxy->to_log &= ~LW_REQHDR;
6497 curproxy->nb_req_cap = 0;
6498 }
6499 }
6500
6501 if (curproxy->nb_rsp_cap) {
6502 if (curproxy->mode == PR_MODE_HTTP) {
6503 curproxy->rsp_cap_pool = create_pool("ptrcap",
6504 curproxy->nb_rsp_cap * sizeof(char *),
6505 MEM_F_SHARED);
6506 } else {
6507 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6508 proxy_type_str(curproxy), curproxy->id);
6509 err_code |= ERR_WARN;
6510 curproxy->to_log &= ~LW_REQHDR;
6511 curproxy->nb_rsp_cap = 0;
6512 }
6513 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006514
Willy Tarreau196729e2012-05-31 19:30:26 +02006515 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006516 if (!(curproxy->cap & PR_CAP_FE)) {
6517 if (curproxy->logformat_string != default_http_log_format &&
6518 curproxy->logformat_string != default_tcp_log_format &&
6519 curproxy->logformat_string != clf_http_log_format)
6520 free(curproxy->logformat_string);
6521 curproxy->logformat_string = NULL;
6522 }
6523
Willy Tarreau196729e2012-05-31 19:30:26 +02006524 if (curproxy->logformat_string)
6525 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6526
6527 if (curproxy->uniqueid_format_string)
6528 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6529
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 /* first, we will invert the servers list order */
6531 newsrv = NULL;
6532 while (curproxy->srv) {
6533 struct server *next;
6534
6535 next = curproxy->srv->next;
6536 curproxy->srv->next = newsrv;
6537 newsrv = curproxy->srv;
6538 if (!next)
6539 break;
6540 curproxy->srv = next;
6541 }
6542
Willy Tarreaudd701652010-05-25 23:03:02 +02006543 /* assign automatic UIDs to servers which don't have one yet */
6544 next_id = 1;
6545 newsrv = curproxy->srv;
6546 while (newsrv != NULL) {
6547 if (!newsrv->puid) {
6548 /* server ID not set, use automatic numbering with first
6549 * spare entry starting with next_svid.
6550 */
6551 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6552 newsrv->conf.id.key = newsrv->puid = next_id;
6553 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6554 }
6555 next_id++;
6556 newsrv = newsrv->next;
6557 }
6558
Willy Tarreau20697042007-11-15 23:26:18 +01006559 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006560 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561
Willy Tarreau62c3be22012-01-20 13:12:32 +01006562 /*
6563 * If this server supports a maxconn parameter, it needs a dedicated
6564 * tasks to fill the emptied slots when a connection leaves.
6565 * Also, resolve deferred tracking dependency if needed.
6566 */
6567 newsrv = curproxy->srv;
6568 while (newsrv != NULL) {
6569 if (newsrv->minconn > newsrv->maxconn) {
6570 /* Only 'minconn' was specified, or it was higher than or equal
6571 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6572 * this will avoid further useless expensive computations.
6573 */
6574 newsrv->maxconn = newsrv->minconn;
6575 } else if (newsrv->maxconn && !newsrv->minconn) {
6576 /* minconn was not specified, so we set it to maxconn */
6577 newsrv->minconn = newsrv->maxconn;
6578 }
6579
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006580#ifdef USE_OPENSSL
6581#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6582#define SSL_OP_NO_COMPRESSION 0
6583#endif
6584#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6585#define SSL_MODE_RELEASE_BUFFERS 0
6586#endif
6587#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6588#define SSL_OP_NO_COMPRESSION 0
6589#endif
6590 if (newsrv->use_ssl) {
6591 int ssloptions =
6592 SSL_OP_ALL | /* all known workarounds for bugs */
6593 SSL_OP_NO_SSLv2 |
6594 SSL_OP_NO_COMPRESSION;
6595 int sslmode =
6596 SSL_MODE_ENABLE_PARTIAL_WRITE |
6597 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6598 SSL_MODE_RELEASE_BUFFERS;
6599
6600 /* Initiate SSL context for current server */
6601 newsrv->ssl_ctx.reused_sess = NULL;
6602 newsrv->data = &ssl_sock;
6603 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6604 if(!newsrv->ssl_ctx.ctx) {
6605
6606 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6607 proxy_type_str(curproxy), curproxy->id,
6608 newsrv->id);
6609 cfgerr++;
6610 goto next_srv;
6611 }
6612
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006613 if (newsrv->ssl_ctx.nosslv3)
6614 ssloptions |= SSL_OP_NO_SSLv3;
6615 if (newsrv->ssl_ctx.notlsv1)
6616 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006617 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6618 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6619 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6620 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006621 if (newsrv->ssl_ctx.ciphers &&
6622 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6623 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6624 curproxy->id, newsrv->id,
6625 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6626 cfgerr++;
6627 goto next_srv;
6628 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006629 }
6630#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006631 if (newsrv->trackit) {
6632 struct proxy *px;
6633 struct server *srv;
6634 char *pname, *sname;
6635
6636 pname = newsrv->trackit;
6637 sname = strrchr(pname, '/');
6638
6639 if (sname)
6640 *sname++ = '\0';
6641 else {
6642 sname = pname;
6643 pname = NULL;
6644 }
6645
6646 if (pname) {
6647 px = findproxy(pname, PR_CAP_BE);
6648 if (!px) {
6649 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6650 proxy_type_str(curproxy), curproxy->id,
6651 newsrv->id, pname);
6652 cfgerr++;
6653 goto next_srv;
6654 }
6655 } else
6656 px = curproxy;
6657
6658 srv = findserver(px, sname);
6659 if (!srv) {
6660 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6661 proxy_type_str(curproxy), curproxy->id,
6662 newsrv->id, sname);
6663 cfgerr++;
6664 goto next_srv;
6665 }
6666
6667 if (!(srv->state & SRV_CHECKED)) {
6668 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6669 "tracking as it does not have checks enabled.\n",
6670 proxy_type_str(curproxy), curproxy->id,
6671 newsrv->id, px->id, srv->id);
6672 cfgerr++;
6673 goto next_srv;
6674 }
6675
6676 if (curproxy != px &&
6677 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6678 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6679 "tracking: disable-on-404 option inconsistency.\n",
6680 proxy_type_str(curproxy), curproxy->id,
6681 newsrv->id, px->id, srv->id);
6682 cfgerr++;
6683 goto next_srv;
6684 }
6685
6686 /* if the other server is forced disabled, we have to do the same here */
6687 if (srv->state & SRV_MAINTAIN) {
6688 newsrv->state |= SRV_MAINTAIN;
6689 newsrv->state &= ~SRV_RUNNING;
6690 newsrv->health = 0;
6691 }
6692
6693 newsrv->track = srv;
6694 newsrv->tracknext = srv->tracknext;
6695 srv->tracknext = newsrv;
6696
6697 free(newsrv->trackit);
6698 newsrv->trackit = NULL;
6699 }
6700 next_srv:
6701 newsrv = newsrv->next;
6702 }
6703
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006704 /* We have to initialize the server lookup mechanism depending
6705 * on what LB algorithm was choosen.
6706 */
6707
6708 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6709 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6710 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006711 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6712 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6713 init_server_map(curproxy);
6714 } else {
6715 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6716 fwrr_init_server_groups(curproxy);
6717 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006718 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006719
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006720 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006721 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6722 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6723 fwlc_init_server_tree(curproxy);
6724 } else {
6725 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6726 fas_init_server_tree(curproxy);
6727 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006728 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006729
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006730 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006731 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6732 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6733 chash_init_server_tree(curproxy);
6734 } else {
6735 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6736 init_server_map(curproxy);
6737 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006738 break;
6739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006740
6741 if (curproxy->options & PR_O_LOGASAP)
6742 curproxy->to_log &= ~LW_BYTES;
6743
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006744 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006745 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006746 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6747 proxy_type_str(curproxy), curproxy->id);
6748 err_code |= ERR_WARN;
6749 }
6750
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006751 if (curproxy->mode != PR_MODE_HTTP) {
6752 int optnum;
6753
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006754 if (curproxy->uri_auth) {
6755 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6756 proxy_type_str(curproxy), curproxy->id);
6757 err_code |= ERR_WARN;
6758 curproxy->uri_auth = NULL;
6759 }
6760
Willy Tarreau87cf5142011-08-19 22:57:24 +02006761 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006762 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6763 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6764 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006765 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006766 }
6767
6768 if (curproxy->options & PR_O_ORGTO) {
6769 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6770 "originalto", proxy_type_str(curproxy), curproxy->id);
6771 err_code |= ERR_WARN;
6772 curproxy->options &= ~PR_O_ORGTO;
6773 }
6774
6775 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6776 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6777 (curproxy->cap & cfg_opts[optnum].cap) &&
6778 (curproxy->options & cfg_opts[optnum].val)) {
6779 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6780 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6781 err_code |= ERR_WARN;
6782 curproxy->options &= ~cfg_opts[optnum].val;
6783 }
6784 }
6785
6786 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6787 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6788 (curproxy->cap & cfg_opts2[optnum].cap) &&
6789 (curproxy->options2 & cfg_opts2[optnum].val)) {
6790 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6791 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6792 err_code |= ERR_WARN;
6793 curproxy->options2 &= ~cfg_opts2[optnum].val;
6794 }
6795 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006796
Willy Tarreauefa5f512010-03-30 20:13:29 +02006797#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006798 if (curproxy->bind_hdr_occ) {
6799 curproxy->bind_hdr_occ = 0;
6800 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6801 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6802 err_code |= ERR_WARN;
6803 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006804#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006805 }
6806
Willy Tarreaubaaee002006-06-26 02:48:02 +02006807 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006808 * ensure that we're not cross-dressing a TCP server into HTTP.
6809 */
6810 newsrv = curproxy->srv;
6811 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006812 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006813 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006815 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006816 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006817
Willy Tarreau0cec3312011-10-31 13:49:26 +01006818 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6819 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6820 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6821 err_code |= ERR_WARN;
6822 }
6823
Willy Tarreauefa5f512010-03-30 20:13:29 +02006824#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006825 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6826 newsrv->bind_hdr_occ = 0;
6827 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6828 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6829 err_code |= ERR_WARN;
6830 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006831#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006832 newsrv = newsrv->next;
6833 }
6834
Willy Tarreauc1a21672009-08-16 22:37:44 +02006835 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006836 curproxy->accept = frontend_accept;
6837
Willy Tarreauc1a21672009-08-16 22:37:44 +02006838 if (curproxy->tcp_req.inspect_delay ||
6839 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006840 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006841
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006842 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006843 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006844 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006845 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006846
6847 /* both TCP and HTTP must check switching rules */
6848 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6849 }
6850
6851 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006852 if (curproxy->tcp_req.inspect_delay ||
6853 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6854 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6855
Emeric Brun97679e72010-09-23 17:56:44 +02006856 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6857 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6858
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006859 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006860 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006861 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006862 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006863
6864 /* If the backend does requires RDP cookie persistence, we have to
6865 * enable the corresponding analyser.
6866 */
6867 if (curproxy->options2 & PR_O2_RDPC_PRST)
6868 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6869 }
6870
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006871 listener = NULL;
6872 while (curproxy->listen) {
6873 struct listener *next;
6874
6875 next = curproxy->listen->next;
6876 curproxy->listen->next = listener;
6877 listener = curproxy->listen;
6878
6879 if (!next)
6880 break;
6881
6882 curproxy->listen = next;
6883 }
6884
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006885#ifdef USE_OPENSSL
6886#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
6887#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
6888#endif
6889
6890#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6891#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6892#endif
6893#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6894#define SSL_OP_NO_COMPRESSION 0
6895#endif
6896#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6897#define SSL_MODE_RELEASE_BUFFERS 0
6898#endif
6899 /* Configure SSL for each bind line.
6900 * Note: if configuration fails at some point, the ->ctx member
6901 * remains NULL so that listeners can later detach.
6902 */
6903 list_for_each_entry(ssl_conf, &curproxy->conf.ssl_bind, by_fe) {
6904 int ssloptions =
6905 SSL_OP_ALL | /* all known workarounds for bugs */
6906 SSL_OP_NO_SSLv2 |
6907 SSL_OP_NO_COMPRESSION |
6908 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6909 int sslmode =
6910 SSL_MODE_ENABLE_PARTIAL_WRITE |
6911 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6912 SSL_MODE_RELEASE_BUFFERS;
6913 SSL_CTX *ctx;
6914
6915 if (!ssl_conf->cert) {
6916 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'ssl').\n",
6917 curproxy->id, ssl_conf->arg, ssl_conf->file, ssl_conf->line);
6918 cfgerr++;
6919 continue;
6920 }
6921
6922 ctx = SSL_CTX_new(SSLv23_server_method());
6923 if (!ctx) {
6924 Alert("Proxy '%s': unable to allocate SSL context for bind '%s' at [%s:%d] using cert '%s'.\n",
6925 curproxy->id, ssl_conf->arg, ssl_conf->file, ssl_conf->line, ssl_conf->cert);
6926 cfgerr++;
6927 continue;
6928 }
6929 if (ssl_conf->nosslv3)
6930 ssloptions |= SSL_OP_NO_SSLv3;
6931 if (ssl_conf->notlsv1)
6932 ssloptions |= SSL_OP_NO_TLSv1;
6933 if (ssl_conf->prefer_server_ciphers)
6934 ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
6935 SSL_CTX_set_options(ctx, ssloptions);
6936 SSL_CTX_set_mode(ctx, sslmode);
6937 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
6938 if (shared_context_init(global.tune.sslcachesize) < 0) {
6939 Alert("Unable to allocate SSL session cache.\n");
6940 cfgerr++;
6941 SSL_CTX_free(ctx);
6942 continue;
6943 }
6944 shared_context_set_cache(ctx);
6945 if (ssl_conf->ciphers &&
6946 !SSL_CTX_set_cipher_list(ctx, ssl_conf->ciphers)) {
6947 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d] using cert '%s'.\n",
6948 curproxy->id, ssl_conf->ciphers, ssl_conf->arg,
6949 ssl_conf->file, ssl_conf->line, ssl_conf->cert);
6950 cfgerr++;
6951 SSL_CTX_free(ctx);
6952 continue;
6953 }
6954
6955 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
6956
6957 if (SSL_CTX_use_PrivateKey_file(ctx, ssl_conf->cert, SSL_FILETYPE_PEM) <= 0) {
6958 Alert("Proxy '%s': unable to load SSL private key from file '%s' in bind '%s' at [%s:%d].\n",
6959 curproxy->id, ssl_conf->cert, ssl_conf->arg, ssl_conf->file, ssl_conf->line);
6960 cfgerr++;
6961 SSL_CTX_free(ctx);
6962 continue;
6963 }
6964
6965 if (SSL_CTX_use_certificate_chain_file(ctx, ssl_conf->cert) <= 0) {
6966 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in bind '%s' at [%s:%d].\n",
6967 curproxy->id, ssl_conf->cert, ssl_conf->arg, ssl_conf->file, ssl_conf->line);
6968 cfgerr++;
6969 SSL_CTX_free(ctx);
6970 continue;
6971 }
6972
6973 ssl_conf->ctx = ctx;
6974 }
6975#endif /* USE_OPENSSL */
6976
Willy Tarreaue6b98942007-10-29 01:09:36 +01006977 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006978 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006979 listener = curproxy->listen;
6980 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006981 if (!listener->luid) {
6982 /* listener ID not set, use automatic numbering with first
6983 * spare entry starting with next_luid.
6984 */
6985 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6986 listener->conf.id.key = listener->luid = next_id;
6987 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006988 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006989 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006990
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006991 /* enable separate counters */
6992 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6993 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6994 if (!listener->name) {
6995 sprintf(trash, "sock-%d", listener->luid);
6996 listener->name = strdup(trash);
6997 }
6998 }
Emeric Brun6e159292012-05-18 16:32:13 +02006999#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007000 if (listener->ssl_conf) {
7001 if (listener->ssl_conf->ctx) {
7002 listener->data = &ssl_sock; /* SSL data layer */
Emeric Brun6e159292012-05-18 16:32:13 +02007003 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007004 else {
7005 listener->ssl_conf->ref_cnt--;
7006 listener->ssl_conf = NULL;
Emeric Brun6e159292012-05-18 16:32:13 +02007007 }
7008 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007009#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +01007010 if (curproxy->options & PR_O_TCP_NOLING)
7011 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007012 if (!listener->maxconn)
7013 listener->maxconn = curproxy->maxconn;
7014 if (!listener->backlog)
7015 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007016 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007017 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02007018 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007019 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007020 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007021
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007022 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7023 listener->options |= LI_O_TCP_RULES;
7024
Willy Tarreaude3041d2010-05-31 10:56:17 +02007025 if (curproxy->mon_mask.s_addr)
7026 listener->options |= LI_O_CHK_MONNET;
7027
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007028 /* smart accept mode is automatic in HTTP mode */
7029 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007030 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_conf) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007031 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7032 listener->options |= LI_O_NOQUICKACK;
7033
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02007034 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01007035 listener = listener->next;
7036 }
7037
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007038#ifdef USE_OPENSSL
7039 /* Release unused SSL configs.
7040 */
7041 list_for_each_entry_safe(ssl_conf, ssl_back, &curproxy->conf.ssl_bind, by_fe) {
7042 if (ssl_conf->ref_cnt)
7043 continue;
7044
7045 if (ssl_conf->ctx)
7046 SSL_CTX_free(ssl_conf->ctx);
7047 free(ssl_conf->ciphers);
7048 free(ssl_conf->cert);
7049 free(ssl_conf->file);
7050 free(ssl_conf->arg);
7051 LIST_DEL(&ssl_conf->by_fe);
7052 free(ssl_conf);
7053 }
7054#endif /* USE_OPENSSL */
7055
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007056 /* Check multi-process mode compatibility for the current proxy */
7057 if (global.nbproc > 1) {
7058 int nbproc = 0;
7059 if (curproxy->bind_proc) {
7060 int proc;
7061 for (proc = 0; proc < global.nbproc; proc++) {
7062 if (curproxy->bind_proc & (1 << proc)) {
7063 nbproc++;
7064 }
7065 }
7066 } else {
7067 nbproc = global.nbproc;
7068 }
7069 if (curproxy->table.peers.name) {
7070 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7071 curproxy->id);
7072 cfgerr++;
7073 }
7074 if (nbproc > 1) {
7075 if (curproxy->uri_auth) {
7076 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7077 curproxy->id);
7078 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7079 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7080 curproxy->id);
7081 }
7082 }
7083 if (curproxy->appsession_name) {
7084 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7085 curproxy->id);
7086 }
7087 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7088 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7089 curproxy->id);
7090 }
7091 }
7092 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007093
7094 /* create the task associated with the proxy */
7095 curproxy->task = task_new();
7096 if (curproxy->task) {
7097 curproxy->task->context = curproxy;
7098 curproxy->task->process = manage_proxy;
7099 /* no need to queue, it will be done automatically if some
7100 * listener gets limited.
7101 */
7102 curproxy->task->expire = TICK_ETERNITY;
7103 } else {
7104 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7105 curproxy->id);
7106 cfgerr++;
7107 }
7108
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109 curproxy = curproxy->next;
7110 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007111
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007112 /* Check multi-process mode compatibility */
7113 if (global.nbproc > 1) {
7114 if (global.stats_fe) {
7115 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
7116 }
7117 }
7118
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007119 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7120 struct auth_users *curuser;
7121 int g;
7122
7123 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7124 unsigned int group_mask = 0;
7125 char *group = NULL;
7126
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007127 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007128 continue;
7129
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007130 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007131
7132 for (g = 0; g < curuserlist->grpcnt; g++)
7133 if (!strcmp(curuserlist->groups[g], group))
7134 break;
7135
7136 if (g == curuserlist->grpcnt) {
7137 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7138 curuserlist->name, group, curuser->user);
7139 err_code |= ERR_ALERT | ERR_FATAL;
7140 goto out;
7141 }
7142
7143 group_mask |= (1 << g);
7144 }
7145
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007146 free(curuser->u.groups);
7147 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007148 }
7149
7150 for (g = 0; g < curuserlist->grpcnt; g++) {
7151 char *user = NULL;
7152
7153 if (!curuserlist->groupusers[g])
7154 continue;
7155
7156 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7157 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7158 if (!strcmp(curuser->user, user))
7159 break;
7160
7161 if (!curuser) {
7162 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7163 curuserlist->name, user, curuserlist->groups[g]);
7164 err_code |= ERR_ALERT | ERR_FATAL;
7165 goto out;
7166 }
7167
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007168 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007169 }
7170
7171 free(curuserlist->groupusers[g]);
7172 }
7173
7174 free(curuserlist->groupusers);
7175
7176#ifdef DEBUG_AUTH
7177 for (g = 0; g < curuserlist->grpcnt; g++) {
7178 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7179
7180 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007181 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007182 fprintf(stderr, " %s", curuser->user);
7183 }
7184
7185 fprintf(stderr, "\n");
7186 }
7187#endif
7188
Willy Tarreaufbb78422011-06-05 15:38:35 +02007189 }
7190
7191 /* automatically compute fullconn if not set. We must not do it in the
7192 * loop above because cross-references are not yet fully resolved.
7193 */
7194 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7195 /* If <fullconn> is not set, let's set it to 10% of the sum of
7196 * the possible incoming frontend's maxconns.
7197 */
7198 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7199 struct proxy *fe;
7200 int total = 0;
7201
7202 /* sum up the number of maxconns of frontends which
7203 * reference this backend at least once or which are
7204 * the same one ('listen').
7205 */
7206 for (fe = proxy; fe; fe = fe->next) {
7207 struct switching_rule *rule;
7208 struct hdr_exp *exp;
7209 int found = 0;
7210
7211 if (!(fe->cap & PR_CAP_FE))
7212 continue;
7213
7214 if (fe == curproxy) /* we're on a "listen" instance */
7215 found = 1;
7216
7217 if (fe->defbe.be == curproxy) /* "default_backend" */
7218 found = 1;
7219
7220 /* check if a "use_backend" rule matches */
7221 if (!found) {
7222 list_for_each_entry(rule, &fe->switching_rules, list) {
7223 if (rule->be.backend == curproxy) {
7224 found = 1;
7225 break;
7226 }
7227 }
7228 }
7229
7230 /* check if a "reqsetbe" rule matches */
7231 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7232 if (exp->action == ACT_SETBE &&
7233 (struct proxy *)exp->replace == curproxy) {
7234 found = 1;
7235 break;
7236 }
7237 }
7238
7239 /* now we've checked all possible ways to reference a backend
7240 * from a frontend.
7241 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007242 if (!found)
7243 continue;
7244 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007245 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007246 /* we have the sum of the maxconns in <total>. We only
7247 * keep 10% of that sum to set the default fullconn, with
7248 * a hard minimum of 1 (to avoid a divide by zero).
7249 */
7250 curproxy->fullconn = (total + 9) / 10;
7251 if (!curproxy->fullconn)
7252 curproxy->fullconn = 1;
7253 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007254 }
7255
Willy Tarreau056f5682010-06-06 15:51:11 +02007256 /* initialize stick-tables on backend capable proxies. This must not
7257 * be done earlier because the data size may be discovered while parsing
7258 * other proxies.
7259 */
7260 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007261 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007262
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007263 /*
7264 * Recount currently required checks.
7265 */
7266
7267 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7268 int optnum;
7269
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007270 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7271 if (curproxy->options & cfg_opts[optnum].val)
7272 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007273
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007274 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7275 if (curproxy->options2 & cfg_opts2[optnum].val)
7276 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007277 }
7278
Willy Tarreau122541c2011-09-07 21:24:49 +02007279 if (peers) {
7280 struct peers *curpeers = peers, **last;
7281 struct peer *p, *pb;
7282
7283 /* Remove all peers sections which don't have a valid listener.
7284 * This can happen when a peers section is never referenced and
7285 * does not contain a local peer.
7286 */
7287 last = &peers;
7288 while (*last) {
7289 curpeers = *last;
7290 if (curpeers->peers_fe) {
7291 last = &curpeers->next;
7292 continue;
7293 }
7294
7295 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7296 curpeers->id, localpeer);
7297
7298 p = curpeers->remote;
7299 while (p) {
7300 pb = p->next;
7301 free(p->id);
7302 free(p);
7303 p = pb;
7304 }
7305
7306 /* Destroy and unlink this curpeers section.
7307 * Note: curpeers is backed up into *last.
7308 */
7309 free(curpeers->id);
7310 curpeers = curpeers->next;
7311 free(*last);
7312 *last = curpeers;
7313 }
7314 }
7315
Willy Tarreauac1932d2011-10-24 19:14:41 +02007316 if (!global.tune.max_http_hdr)
7317 global.tune.max_http_hdr = MAX_HTTP_HDR;
7318
Willy Tarreau34eb6712011-10-24 18:15:04 +02007319 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007320 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007321 MEM_F_SHARED);
7322
Willy Tarreaubb925012009-07-23 13:36:36 +02007323 if (cfgerr > 0)
7324 err_code |= ERR_ALERT | ERR_FATAL;
7325 out:
7326 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007327}
7328
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007329/*
7330 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7331 * parsing sessions.
7332 */
7333void cfg_register_keywords(struct cfg_kw_list *kwl)
7334{
7335 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7336}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007337
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007338/*
7339 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7340 */
7341void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7342{
7343 LIST_DEL(&kwl->list);
7344 LIST_INIT(&kwl->list);
7345}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346
7347/*
7348 * Local variables:
7349 * c-indent-level: 8
7350 * c-basic-offset: 8
7351 * End:
7352 */