blob: 07b73471c48a38dcd403ea54fc714cbbaa13f143 [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 Tarreaud1d54542012-09-12 22:58:11 +020054#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020056#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100114struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 const char *name;
116 unsigned int val;
117 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100118 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100119 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100120};
121
122/* proxy->options */
123static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100124{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100125 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
126 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
127 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
129 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
130 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
131 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
135 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
136 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
137 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
138 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
139 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
140 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100141#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100143#else
144 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100145#endif
146
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148};
149
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150/* proxy->options2 */
151static const struct cfg_opt cfg_opts2[] =
152{
153#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
155 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100157#else
158 { "splice-request", 0, 0, 0, 0 },
159 { "splice-response", 0, 0, 0, 0 },
160 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100161#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
163 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
165 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
166 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
167 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
168 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
170 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400171 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200173 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200174 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100175 { NULL, 0, 0, 0 }
176};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177
Willy Tarreau6daf3432008-01-22 16:44:08 +0100178static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
180int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100181int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200183/* List head of all known configuration keywords */
184static struct cfg_kw_list cfg_keywords = {
185 .list = LIST_HEAD_INIT(cfg_keywords.list)
186};
187
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188/*
189 * converts <str> to a list of listeners which are dynamically allocated.
190 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
191 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
192 * - <port> is a numerical port from 1 to 65535 ;
193 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
194 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200195 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100197static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
206 struct sockaddr_storage ss;
207
208 str = next;
209 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100210 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 *next++ = 0;
212 }
213
Emeric Bruned760922010-10-22 17:59:25 +0200214 if (*str == '/') {
215 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
216 /* so compute max path */
217 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
218 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 +0200219
Emeric Bruned760922010-10-22 17:59:25 +0200220 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100221 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
222 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200223 goto fail;
224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200227 ss.ss_family = AF_UNIX;
228 if (global.unix_bind.prefix) {
229 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
230 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 }
Emeric Bruned760922010-10-22 17:59:25 +0200232 else {
233 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
234 }
235 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 }
237 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 ss2 = str2sa_range(str, &port, &end);
241 if (!ss2) {
242 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
243 file, line, str);
244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 if (!port) {
248 Alert("parsing [%s:%d] : missing port number: '%s'\n",
249 file, line, str);
250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100257 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
258 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100263 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
264 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200265 goto fail;
266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 }
268
269 for (; port <= end; port++) {
270 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271 l->next = curproxy->listen;
272 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
274 l->fd = -1;
275 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200276 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
288 l->perm.ux.gid = l->perm.ux.uid = -1;
289 l->perm.ux.mode = 0;
290 uxst_add_listener(l);
291 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200292
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200293 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100294 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 } /* end for(port) */
296 } /* end while(next) */
297 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 fail:
300 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200301 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302}
303
Willy Tarreau977b8e42006-12-29 14:19:17 +0100304/*
305 * Sends a warning if proxy <proxy> does not have at least one of the
306 * capabilities in <cap>. An optionnal <hint> may be added at the end
307 * of the warning to help the user. Returns 1 if a warning was emitted
308 * or 0 if the condition is valid.
309 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100310int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100311{
312 char *msg;
313
314 switch (cap) {
315 case PR_CAP_BE: msg = "no backend"; break;
316 case PR_CAP_FE: msg = "no frontend"; break;
317 case PR_CAP_RS: msg = "no ruleset"; break;
318 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
319 default: msg = "not enough"; break;
320 }
321
322 if (!(proxy->cap & cap)) {
323 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100324 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100325 return 1;
326 }
327 return 0;
328}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200329
Willy Tarreau61d18892009-03-31 10:49:21 +0200330/* Report a warning if a rule is placed after a 'block' rule.
331 * Return 1 if the warning has been emitted, otherwise 0.
332 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100333int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200334{
335 if (!LIST_ISEMPTY(&proxy->block_cond)) {
336 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
337 file, line, arg);
338 return 1;
339 }
340 return 0;
341}
342
343/* Report a warning if a rule is placed after a reqrewrite rule.
344 * Return 1 if the warning has been emitted, otherwise 0.
345 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100346int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200347{
348 if (proxy->req_exp) {
349 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
350 file, line, arg);
351 return 1;
352 }
353 return 0;
354}
355
356/* Report a warning if a rule is placed after a reqadd rule.
357 * Return 1 if the warning has been emitted, otherwise 0.
358 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100359int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200360{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100361 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200362 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
363 file, line, arg);
364 return 1;
365 }
366 return 0;
367}
368
369/* Report a warning if a rule is placed after a redirect rule.
370 * Return 1 if the warning has been emitted, otherwise 0.
371 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100372int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200373{
374 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
375 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
376 file, line, arg);
377 return 1;
378 }
379 return 0;
380}
381
382/* Report a warning if a rule is placed after a 'use_backend' rule.
383 * Return 1 if the warning has been emitted, otherwise 0.
384 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
388 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
389 file, line, arg);
390 return 1;
391 }
392 return 0;
393}
394
395/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100396int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200397{
398 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
399 warnif_rule_after_reqadd(proxy, file, line, arg) ||
400 warnif_rule_after_redirect(proxy, file, line, arg) ||
401 warnif_rule_after_use_backend(proxy, file, line, arg);
402}
403
404/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
408 warnif_rule_after_redirect(proxy, file, line, arg) ||
409 warnif_rule_after_use_backend(proxy, file, line, arg);
410}
411
412/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100413int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200414{
415 return warnif_rule_after_redirect(proxy, file, line, arg) ||
416 warnif_rule_after_use_backend(proxy, file, line, arg);
417}
418
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100419/* Report it if a request ACL condition uses some response-only parameters. It
420 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
421 * Note that <cond> may be NULL and then will be ignored.
422 */
423static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
424{
425 struct acl *acl;
426
427 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
428 return 0;
429
430 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
431 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
432 file, line, acl ? acl->name : "(unknown)");
433 return ERR_WARN;
434}
435
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100436/* Report it if a request ACL condition uses some request-only volatile parameters.
437 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
438 * Note that <cond> may be NULL and then will be ignored.
439 */
440static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
441{
442 struct acl *acl;
443
444 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
445 return 0;
446
447 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
448 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
449 file, line, acl ? acl->name : "(unknown)");
450 return ERR_WARN;
451}
452
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100453
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200455 * parse a line in a <global> section. Returns the error code, 0 if OK, or
456 * any combination of :
457 * - ERR_ABORT: must abort ASAP
458 * - ERR_FATAL: we can continue parsing but not start the service
459 * - ERR_WARN: a warning has been emitted
460 * - ERR_ALERT: an alert has been emitted
461 * Only the two first ones can stop processing, the two others are just
462 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200464int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465{
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200467 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468
469 if (!strcmp(args[0], "global")) { /* new section */
470 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472 }
473 else if (!strcmp(args[0], "daemon")) {
474 global.mode |= MODE_DAEMON;
475 }
476 else if (!strcmp(args[0], "debug")) {
477 global.mode |= MODE_DEBUG;
478 }
479 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100480 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100483 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200484 }
485 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100486 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100489 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100491 else if (!strcmp(args[0], "nosplice")) {
492 global.tune.options &= ~GTUNE_USE_SPLICE;
493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200494 else if (!strcmp(args[0], "quiet")) {
495 global.mode |= MODE_QUIET;
496 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200497 else if (!strcmp(args[0], "tune.maxpollevents")) {
498 if (global.tune.maxpollevents != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200507 }
508 global.tune.maxpollevents = atol(args[1]);
509 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100510 else if (!strcmp(args[0], "tune.maxaccept")) {
511 if (global.tune.maxaccept != 0) {
512 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT;
514 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100515 }
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200518 err_code |= ERR_ALERT | ERR_FATAL;
519 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100520 }
521 global.tune.maxaccept = atol(args[1]);
522 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200523 else if (!strcmp(args[0], "tune.chksize")) {
524 if (*(args[1]) == 0) {
525 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
526 err_code |= ERR_ALERT | ERR_FATAL;
527 goto out;
528 }
529 global.tune.chksize = atol(args[1]);
530 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200531#ifdef USE_OPENSSL
532 else if (!strcmp(args[0], "tune.sslcachesize")) {
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
537 }
538 global.tune.sslcachesize = atol(args[1]);
539 }
540#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200541 else if (!strcmp(args[0], "tune.bufsize")) {
542 if (*(args[1]) == 0) {
543 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
546 }
547 global.tune.bufsize = atol(args[1]);
548 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
549 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200550 trashlen = global.tune.bufsize;
551 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200552 }
553 else if (!strcmp(args[0], "tune.maxrewrite")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.maxrewrite = atol(args[1]);
560 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
561 global.tune.maxrewrite = global.tune.bufsize / 2;
562 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100563 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
564 if (global.tune.client_rcvbuf != 0) {
565 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT;
567 goto out;
568 }
569 if (*(args[1]) == 0) {
570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
573 }
574 global.tune.client_rcvbuf = atol(args[1]);
575 }
576 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
577 if (global.tune.server_rcvbuf != 0) {
578 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT;
580 goto out;
581 }
582 if (*(args[1]) == 0) {
583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587 global.tune.server_rcvbuf = atol(args[1]);
588 }
589 else if (!strcmp(args[0], "tune.sndbuf.client")) {
590 if (global.tune.client_sndbuf != 0) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.client_sndbuf = atol(args[1]);
601 }
602 else if (!strcmp(args[0], "tune.sndbuf.server")) {
603 if (global.tune.server_sndbuf != 0) {
604 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT;
606 goto out;
607 }
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
610 err_code |= ERR_ALERT | ERR_FATAL;
611 goto out;
612 }
613 global.tune.server_sndbuf = atol(args[1]);
614 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200615 else if (!strcmp(args[0], "tune.pipesize")) {
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.pipesize = atol(args[1]);
622 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200623 else if (!strcmp(args[0], "tune.http.maxhdr")) {
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628 }
629 global.tune.max_http_hdr = atol(args[1]);
630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 else if (!strcmp(args[0], "uid")) {
632 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.uid = atol(args[1]);
643 }
644 else if (!strcmp(args[0], "gid")) {
645 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200646 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200654 }
655 global.gid = atol(args[1]);
656 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 /* user/group name handling */
658 else if (!strcmp(args[0], "user")) {
659 struct passwd *ha_user;
660 if (global.uid != 0) {
661 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT;
663 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200664 }
665 errno = 0;
666 ha_user = getpwnam(args[1]);
667 if (ha_user != NULL) {
668 global.uid = (int)ha_user->pw_uid;
669 }
670 else {
671 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 +0200672 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200673 }
674 }
675 else if (!strcmp(args[0], "group")) {
676 struct group *ha_group;
677 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200678 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT;
680 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200681 }
682 errno = 0;
683 ha_group = getgrnam(args[1]);
684 if (ha_group != NULL) {
685 global.gid = (int)ha_group->gr_gid;
686 }
687 else {
688 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 +0200689 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200690 }
691 }
692 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 else if (!strcmp(args[0], "nbproc")) {
694 if (global.nbproc != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.nbproc = atol(args[1]);
705 }
706 else if (!strcmp(args[0], "maxconn")) {
707 if (global.maxconn != 0) {
708 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 }
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 global.maxconn = atol(args[1]);
718#ifdef SYSTEM_MAXCONN
719 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
720 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);
721 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200722 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200723 }
724#endif /* SYSTEM_MAXCONN */
725 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200726 else if (!strcmp(args[0], "maxsslconn")) {
727#ifdef USE_OPENSSL
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 global.maxsslconn = atol(args[1]);
734#else
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740#endif
741 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200742 else if (!strcmp(args[0], "maxconnrate")) {
743 if (global.cps_lim != 0) {
744 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
745 err_code |= ERR_ALERT;
746 goto out;
747 }
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
752 }
753 global.cps_lim = atol(args[1]);
754 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100755 else if (!strcmp(args[0], "maxpipes")) {
756 if (global.maxpipes != 0) {
757 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT;
759 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100760 }
761 if (*(args[1]) == 0) {
762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100765 }
766 global.maxpipes = atol(args[1]);
767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 else if (!strcmp(args[0], "ulimit-n")) {
769 if (global.rlimit_nofile != 0) {
770 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774 if (*(args[1]) == 0) {
775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 }
779 global.rlimit_nofile = atol(args[1]);
780 }
781 else if (!strcmp(args[0], "chroot")) {
782 if (global.chroot != NULL) {
783 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT;
785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
787 if (*(args[1]) == 0) {
788 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200789 err_code |= ERR_ALERT | ERR_FATAL;
790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200791 }
792 global.chroot = strdup(args[1]);
793 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200794 else if (!strcmp(args[0], "description")) {
795 int i, len=0;
796 char *d;
797
798 if (!*args[1]) {
799 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
800 file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804
805 for(i=1; *args[i]; i++)
806 len += strlen(args[i])+1;
807
808 if (global.desc)
809 free(global.desc);
810
811 global.desc = d = (char *)calloc(1, len);
812
813 d += sprintf(d, "%s", args[1]);
814 for(i=2; *args[i]; i++)
815 d += sprintf(d, " %s", args[i]);
816 }
817 else if (!strcmp(args[0], "node")) {
818 int i;
819 char c;
820
821 for (i=0; args[1][i]; i++) {
822 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100823 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
824 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200825 break;
826 }
827
828 if (!i || args[1][i]) {
829 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
830 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
831 file, linenum, args[0]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835
836 if (global.node)
837 free(global.node);
838
839 global.node = strdup(args[1]);
840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 else if (!strcmp(args[0], "pidfile")) {
842 if (global.pidfile != NULL) {
843 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200844 err_code |= ERR_ALERT;
845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847 if (*(args[1]) == 0) {
848 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200851 }
852 global.pidfile = strdup(args[1]);
853 }
Emeric Bruned760922010-10-22 17:59:25 +0200854 else if (!strcmp(args[0], "unix-bind")) {
855 int cur_arg = 1;
856 while (*(args[cur_arg])) {
857 if (!strcmp(args[cur_arg], "prefix")) {
858 if (global.unix_bind.prefix != NULL) {
859 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
860 err_code |= ERR_ALERT;
861 cur_arg += 2;
862 continue;
863 }
864
865 if (*(args[cur_arg+1]) == 0) {
866 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870 global.unix_bind.prefix = strdup(args[cur_arg+1]);
871 cur_arg += 2;
872 continue;
873 }
874
875 if (!strcmp(args[cur_arg], "mode")) {
876
877 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
878 cur_arg += 2;
879 continue;
880 }
881
882 if (!strcmp(args[cur_arg], "uid")) {
883
884 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
885 cur_arg += 2;
886 continue;
887 }
888
889 if (!strcmp(args[cur_arg], "gid")) {
890
891 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
892 cur_arg += 2;
893 continue;
894 }
895
896 if (!strcmp(args[cur_arg], "user")) {
897 struct passwd *user;
898
899 user = getpwnam(args[cur_arg + 1]);
900 if (!user) {
901 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
902 file, linenum, args[0], args[cur_arg + 1 ]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906
907 global.unix_bind.ux.uid = user->pw_uid;
908 cur_arg += 2;
909 continue;
910 }
911
912 if (!strcmp(args[cur_arg], "group")) {
913 struct group *group;
914
915 group = getgrnam(args[cur_arg + 1]);
916 if (!group) {
917 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
918 file, linenum, args[0], args[cur_arg + 1 ]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922
923 global.unix_bind.ux.gid = group->gr_gid;
924 cur_arg += 2;
925 continue;
926 }
927
Willy Tarreaub48f9582011-09-05 01:17:06 +0200928 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200929 file, linenum, args[0]);
930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
932 }
933 }
William Lallemand0f99e342011-10-12 17:50:54 +0200934 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
935 /* delete previous herited or defined syslog servers */
936 struct logsrv *back;
937 struct logsrv *tmp;
938
939 if (*(args[1]) != 0) {
940 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
941 err_code |= ERR_ALERT | ERR_FATAL;
942 goto out;
943 }
944
945 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
946 LIST_DEL(&tmp->list);
947 free(tmp);
948 }
949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200951 struct logsrv *logsrv;
952
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953 if (*(args[1]) == 0 || *(args[2]) == 0) {
954 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
William Lallemand0f99e342011-10-12 17:50:54 +0200958
959 logsrv = calloc(1, sizeof(struct logsrv));
960
961 logsrv->facility = get_log_facility(args[2]);
962 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200964 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200965 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966 }
967
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200970 logsrv->level = get_log_level(args[3]);
971 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200974 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 }
976 }
977
William Lallemand0f99e342011-10-12 17:50:54 +0200978 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200979 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200980 logsrv->minlvl = get_log_level(args[4]);
981 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200982 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200983 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200984 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200985 }
986 }
987
Robert Tsai81ae1952007-12-05 10:47:29 +0100988 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100989 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100990 if (!sk) {
991 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100992 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100993 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200994 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100995 goto out;
996 }
William Lallemand0f99e342011-10-12 17:50:54 +0200997 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100998 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100999 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001000 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001001 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1002 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001003 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001004 goto out;
1005 }
William Lallemand0f99e342011-10-12 17:50:54 +02001006 logsrv->addr = *sk;
1007 if (!get_host_port(&logsrv->addr))
1008 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010
William Lallemand0f99e342011-10-12 17:50:54 +02001011 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001012 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001013 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1014 char *name;
1015 int len;
1016
1017 if (global.log_send_hostname != NULL) {
1018 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1019 err_code |= ERR_ALERT;
1020 goto out;
1021 }
1022
1023 if (*(args[1]))
1024 name = args[1];
1025 else
1026 name = hostname;
1027
1028 len = strlen(name);
1029
1030 /* We'll add a space after the name to respect the log format */
1031 free(global.log_send_hostname);
1032 global.log_send_hostname = malloc(len + 2);
1033 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1034 }
Kevinm48936af2010-12-22 16:08:21 +00001035 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 free(global.log_tag);
1042 global.log_tag = strdup(args[1]);
1043 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001044 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1045 if (global.spread_checks != 0) {
1046 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT;
1048 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001049 }
1050 if (*(args[1]) == 0) {
1051 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001054 }
1055 global.spread_checks = atol(args[1]);
1056 if (global.spread_checks < 0 || global.spread_checks > 50) {
1057 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 }
1061 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001062 struct cfg_kw_list *kwl;
1063 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001064 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001065
1066 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1067 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1068 if (kwl->kw[index].section != CFG_GLOBAL)
1069 continue;
1070 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1071 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001072 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001073 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001074 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001075 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001076 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001078 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001079 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001080 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001081 err_code |= ERR_WARN;
1082 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001083 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001084 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001085 }
1086 }
1087 }
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001092
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001094 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096}
1097
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001098void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001100 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 defproxy.mode = PR_MODE_TCP;
1102 defproxy.state = PR_STNEW;
1103 defproxy.maxconn = cfg_maxpconn;
1104 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001105
1106 defproxy.defsrv.inter = DEF_CHKINTR;
1107 defproxy.defsrv.fastinter = 0;
1108 defproxy.defsrv.downinter = 0;
1109 defproxy.defsrv.rise = DEF_RISETIME;
1110 defproxy.defsrv.fall = DEF_FALLTIME;
1111 defproxy.defsrv.check_port = 0;
1112 defproxy.defsrv.maxqueue = 0;
1113 defproxy.defsrv.minconn = 0;
1114 defproxy.defsrv.maxconn = 0;
1115 defproxy.defsrv.slowstart = 0;
1116 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1117 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1118 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119}
1120
Willy Tarreauade5ec42010-01-28 19:33:49 +01001121
1122static int create_cond_regex_rule(const char *file, int line,
1123 struct proxy *px, int dir, int action, int flags,
1124 const char *cmd, const char *reg, const char *repl,
1125 const char **cond_start)
1126{
1127 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001128 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001129 const char *err;
1130 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001131 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001132
1133 if (px == &defproxy) {
1134 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138
1139 if (*reg == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto err;
1143 }
1144
1145 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1146 err_code |= ERR_WARN;
1147
Willy Tarreau5321c422010-01-28 20:35:13 +01001148 if (cond_start &&
1149 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001150 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1151 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1152 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto err;
1155 }
1156 }
1157 else if (cond_start && **cond_start) {
1158 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1159 file, line, cmd, *cond_start);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001164 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001166 else
1167 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001168
Willy Tarreauade5ec42010-01-28 19:33:49 +01001169 preg = calloc(1, sizeof(regex_t));
1170 if (!preg) {
1171 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1172 err_code = ERR_ALERT | ERR_FATAL;
1173 goto err;
1174 }
1175
1176 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1177 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1178 err_code = ERR_ALERT | ERR_FATAL;
1179 goto err;
1180 }
1181
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001182 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001183 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001184 if (repl && err) {
1185 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1186 file, line, cmd, *err);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto err;
1189 }
1190
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001191 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001192 err_code |= ERR_WARN;
1193
Willy Tarreauf4068b62012-05-08 17:37:49 +02001194 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001195 return err_code;
1196 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001197 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001198 free(preg);
1199 return err_code;
1200}
1201
Willy Tarreaubaaee002006-06-26 02:48:02 +02001202/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001203 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001204 * Returns the error code, 0 if OK, or any combination of :
1205 * - ERR_ABORT: must abort ASAP
1206 * - ERR_FATAL: we can continue parsing but not start the service
1207 * - ERR_WARN: a warning has been emitted
1208 * - ERR_ALERT: an alert has been emitted
1209 * Only the two first ones can stop processing, the two others are just
1210 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001212int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1213{
1214 static struct peers *curpeers = NULL;
1215 struct peer *newpeer = NULL;
1216 const char *err;
1217 int err_code = 0;
1218
1219 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1220
1221 err = invalid_char(args[1]);
1222 if (err) {
1223 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1224 file, linenum, *err, args[0], args[1]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 }
1227
1228 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1229 /*
1230 * If there are two proxies with the same name only following
1231 * combinations are allowed:
1232 */
1233 if (strcmp(curpeers->id, args[1]) == 0) {
1234 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1235 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1236 err_code |= ERR_WARN;
1237 }
1238 }
1239
1240 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1242 err_code |= ERR_ALERT | ERR_ABORT;
1243 goto out;
1244 }
1245
1246 curpeers->next = peers;
1247 peers = curpeers;
1248 curpeers->conf.file = file;
1249 curpeers->conf.line = linenum;
1250 curpeers->last_change = now.tv_sec;
1251 curpeers->id = strdup(args[1]);
1252 }
1253 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1254 char *rport, *raddr;
1255 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001256 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001257
1258 if (!*args[2]) {
1259 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1260 file, linenum, args[0]);
1261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
1263 }
1264
1265 err = invalid_char(args[1]);
1266 if (err) {
1267 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1268 file, linenum, *err, args[1]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272
1273 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 err_code |= ERR_ALERT | ERR_ABORT;
1276 goto out;
1277 }
1278
1279 /* the peers are linked backwards first */
1280 curpeers->count++;
1281 newpeer->next = curpeers->remote;
1282 curpeers->remote = newpeer;
1283 newpeer->peers = curpeers;
1284 newpeer->conf.file = file;
1285 newpeer->conf.line = linenum;
1286
1287 newpeer->last_change = now.tv_sec;
1288 newpeer->id = strdup(args[1]);
1289
1290 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001291 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001292 if (rport) {
1293 *rport++ = 0;
1294 realport = atol(rport);
1295 }
1296 if (!realport) {
1297 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301
Willy Tarreaufab5a432011-03-04 15:31:53 +01001302 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 free(raddr);
1304 if (!sk) {
1305 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1306 err_code |= ERR_ALERT | ERR_FATAL;
1307 goto out;
1308 }
1309 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001310 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001311 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001312 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001313
1314 if (!sk) {
1315 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1316 file, linenum, newpeer->addr.ss_family, args[2]);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001321 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001322
1323 if (strcmp(newpeer->id, localpeer) == 0) {
1324 /* Current is local peer, it define a frontend */
1325 newpeer->local = 1;
1326
1327 if (!curpeers->peers_fe) {
1328 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1329 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1330 err_code |= ERR_ALERT | ERR_ABORT;
1331 goto out;
1332 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001333
Willy Tarreau237250c2011-07-29 01:49:03 +02001334 init_new_proxy(curpeers->peers_fe);
1335 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001336
1337 curpeers->peers_fe->last_change = now.tv_sec;
1338 curpeers->peers_fe->id = strdup(args[1]);
1339 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001340 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001341 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1342 curpeers->peers_fe->timeout.connect = 5000;
1343 curpeers->peers_fe->accept = peer_accept;
1344 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001345 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001346 err_code |= ERR_FATAL;
1347 goto out;
1348 }
1349 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1350 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1351 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1352 curpeers->peers_fe->listen->accept = session_accept;
1353 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1354 curpeers->peers_fe->listen->handler = process_session;
1355 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001356 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1357 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001358 }
1359 }
1360 } /* neither "peer" nor "peers" */
1361 else if (*args[0] != 0) {
1362 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
1365 }
1366
1367out:
1368 return err_code;
1369}
1370
1371
Willy Tarreau3842f002009-06-14 11:39:52 +02001372int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373{
1374 static struct proxy *curproxy = NULL;
1375 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001376 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001377 int rc;
1378 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001379 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001380 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001381 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001382 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001383 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384
Willy Tarreau977b8e42006-12-29 14:19:17 +01001385 if (!strcmp(args[0], "listen"))
1386 rc = PR_CAP_LISTEN;
1387 else if (!strcmp(args[0], "frontend"))
1388 rc = PR_CAP_FE | PR_CAP_RS;
1389 else if (!strcmp(args[0], "backend"))
1390 rc = PR_CAP_BE | PR_CAP_RS;
1391 else if (!strcmp(args[0], "ruleset"))
1392 rc = PR_CAP_RS;
1393 else
1394 rc = PR_CAP_NONE;
1395
1396 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 if (!*args[1]) {
1398 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1399 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001401 err_code |= ERR_ALERT | ERR_ABORT;
1402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001404
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001405 err = invalid_char(args[1]);
1406 if (err) {
1407 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1408 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001410 }
1411
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001412 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1413 /*
1414 * If there are two proxies with the same name only following
1415 * combinations are allowed:
1416 *
1417 * listen backend frontend ruleset
1418 * listen - - - -
1419 * backend - - OK -
1420 * frontend - OK - -
1421 * ruleset - - - -
1422 */
1423
1424 if (!strcmp(curproxy->id, args[1]) &&
1425 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1426 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001427 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1428 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1429 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001430 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001431 }
1432 }
1433
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1435 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001436 err_code |= ERR_ALERT | ERR_ABORT;
1437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001439
Willy Tarreau97cb7802010-01-03 20:23:58 +01001440 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 curproxy->next = proxy;
1442 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001443 curproxy->conf.file = file;
1444 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001445 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448
1449 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001451 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001452 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001453 err_code |= ERR_FATAL;
1454 goto out;
1455 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001456 new = curproxy->listen;
1457 while (new != last) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001458 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 Tarreau2a65ff02012-09-13 17:54:29 +02001690 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
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) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001703 new_listen->bind_conf = bind_conf;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001704 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001705 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001706 }
1707
Emeric Bruned760922010-10-22 17:59:25 +02001708 /* Set default global rights and owner for unix bind */
1709 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1710 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1711 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001712 cur_arg = 2;
1713 while (*(args[cur_arg])) {
1714 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1715#ifdef SO_BINDTODEVICE
1716 struct listener *l;
1717
Emeric Bruned760922010-10-22 17:59:25 +02001718 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1720 file, linenum, args[0], args[cur_arg]);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001725 if (!*args[cur_arg + 1]) {
1726 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001730 }
1731
1732 for (l = curproxy->listen; l != last_listen; l = l->next)
1733 l->interface = strdup(args[cur_arg + 1]);
1734
1735 global.last_checks |= LSTCHK_NETADM;
1736
1737 cur_arg += 2;
1738 continue;
1739#else
1740 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1741 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001744#endif
1745 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001746 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1747#ifdef TCP_MAXSEG
1748 struct listener *l;
1749 int mss;
1750
Emeric Bruned760922010-10-22 17:59:25 +02001751 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1752 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1753 file, linenum, args[0], args[cur_arg]);
1754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
1756 }
1757
Willy Tarreaube1b9182009-06-14 18:48:19 +02001758 if (!*args[cur_arg + 1]) {
1759 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001763 }
1764
Willy Tarreau48a7e722010-12-24 15:26:39 +01001765 mss = atoi(args[cur_arg + 1]);
1766 if (!mss || abs(mss) > 65535) {
1767 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001768 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001771 }
1772
1773 for (l = curproxy->listen; l != last_listen; l = l->next)
1774 l->maxseg = mss;
1775
1776 cur_arg += 2;
1777 continue;
1778#else
1779 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1780 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001783#endif
1784 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001785
1786 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1787#ifdef TCP_DEFER_ACCEPT
1788 struct listener *l;
1789
1790 for (l = curproxy->listen; l != last_listen; l = l->next)
1791 l->options |= LI_O_DEF_ACCEPT;
1792
1793 cur_arg ++;
1794 continue;
1795#else
1796 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1797 file, linenum, args[0], args[cur_arg]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800#endif
1801 }
1802
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001803 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001804#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001805 struct listener *l;
1806
Emeric Bruned760922010-10-22 17:59:25 +02001807 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1808 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1809 file, linenum, args[0], args[cur_arg]);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001814 for (l = curproxy->listen; l != last_listen; l = l->next)
1815 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001816
1817 cur_arg ++;
1818 continue;
1819#else
1820 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1821 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001824#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001825 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001826
Willy Tarreau32368ce2012-09-06 11:10:55 +02001827 if (!strcmp(args[cur_arg], "maxconn")) {
1828 struct listener *l;
1829 int val;
1830
1831 if (!*args[cur_arg + 1]) {
1832 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1833 file, linenum, args[0]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
1838 val = atol(args[cur_arg + 1]);
1839 if (val <= 0) {
1840 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1841 file, linenum, args[0], val);
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845
1846 for (l = curproxy->listen; l != last_listen; l = l->next)
1847 l->maxconn = val;
1848
1849 cur_arg += 2;
1850 continue;
1851 }
1852
1853 if (!strcmp(args[cur_arg], "backlog")) {
1854 struct listener *l;
1855 int val;
1856
1857 if (!*args[cur_arg + 1]) {
1858 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1859 file, linenum, args[0]);
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863
1864 val = atol(args[cur_arg + 1]);
1865 if (val <= 0) {
1866 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1867 file, linenum, args[0], val);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871
1872 for (l = curproxy->listen; l != last_listen; l = l->next)
1873 l->backlog = val;
1874
1875 cur_arg += 2;
1876 continue;
1877 }
1878
Willy Tarreau50acaaa2012-09-06 14:26:36 +02001879 if (!strcmp(args[cur_arg], "nice")) {
1880 struct listener *l;
1881 int val;
1882
1883 if (!*args[cur_arg + 1]) {
1884 Alert("parsing [%s:%d] : '%s' : missing nice value.\n",
1885 file, linenum, args[0]);
1886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
1888 }
1889
1890 val = atol(args[cur_arg + 1]);
1891 if (val < -1024 || val > 1024) {
1892 Alert("parsing [%s:%d] : '%s' : invalid nice value %d, allowed range is -1024..1024.\n",
1893 file, linenum, args[0], val);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898 for (l = curproxy->listen; l != last_listen; l = l->next)
1899 l->nice = val;
1900
1901 cur_arg += 2;
1902 continue;
1903 }
1904
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001905 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl */
Emeric Brun6e159292012-05-18 16:32:13 +02001906#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001907 bind_conf->is_ssl = 1;
Emeric Brunfc0421f2012-09-07 17:30:07 +02001908 cur_arg += 1;
1909 continue;
1910#else
1911 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1912 file, linenum, args[0], args[cur_arg]);
1913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
1915#endif
1916 }
1917
1918 if (!strcmp(args[cur_arg], "crt")) { /* use ssl certificate */
1919#ifdef USE_OPENSSL
1920 if (!*args[cur_arg + 1]) {
1921 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1922 file, linenum, args[0]);
1923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
1925 }
1926
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001927 if (ssl_sock_load_cert(args[cur_arg + 1], bind_conf, curproxy) > 0) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02001928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
1931
Emeric Brun6e159292012-05-18 16:32:13 +02001932 cur_arg += 2;
1933 continue;
1934#else
1935 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1936 file, linenum, args[0], args[cur_arg]);
1937 err_code |= ERR_ALERT | ERR_FATAL;
1938 goto out;
1939#endif
1940 }
1941
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001942 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1943#ifdef USE_OPENSSL
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001944 if (!*args[cur_arg + 1]) {
1945 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1946 file, linenum, args[0]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949 }
1950
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001951 bind_conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001952 cur_arg += 2;
1953 continue;
1954#else
1955 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1956 file, linenum, args[0], args[cur_arg]);
1957 err_code |= ERR_ALERT | ERR_FATAL;
1958 goto out;
1959#endif
1960 }
1961
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001962 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1963#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001964 bind_conf->nosslv3 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001965 cur_arg += 1;
1966 continue;
1967#else
1968 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1969 file, linenum, args[0], args[cur_arg]);
1970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
1972#endif
1973 }
1974
1975 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1976#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001977 bind_conf->notlsv1 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001978 cur_arg += 1;
1979 continue;
1980#else
1981 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1982 file, linenum, args[0], args[cur_arg]);
1983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
1985#endif
1986 }
1987
David BERARDe566ecb2012-09-04 15:15:13 +02001988 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1989#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001990 bind_conf->prefer_server_ciphers = 1;
David BERARDe566ecb2012-09-04 15:15:13 +02001991 cur_arg += 1;
1992 continue;
1993#else
1994 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1995 file, linenum, args[0], args[cur_arg]);
1996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
1998#endif
1999 }
2000
Willy Tarreau8a956912010-10-15 14:27:08 +02002001 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
2002 struct listener *l;
2003
2004 for (l = curproxy->listen; l != last_listen; l = l->next)
2005 l->options |= LI_O_ACC_PROXY;
2006
2007 cur_arg ++;
2008 continue;
2009 }
2010
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002011 if (!strcmp(args[cur_arg], "name")) {
2012 struct listener *l;
2013
2014 for (l = curproxy->listen; l != last_listen; l = l->next)
2015 l->name = strdup(args[cur_arg + 1]);
2016
2017 cur_arg += 2;
2018 continue;
2019 }
2020
2021 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002022 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002023 struct listener *l;
2024
2025 if (curproxy->listen->next != last_listen) {
2026 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
2027 file, linenum, args[cur_arg]);
2028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
2030 }
2031
2032 if (!*args[cur_arg + 1]) {
2033 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2034 file, linenum, args[cur_arg]);
2035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
2037 }
2038
2039 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002040 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002042 if (curproxy->listen->luid <= 0) {
2043 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002044 file, linenum);
2045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
2047 }
2048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002049 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
2050 if (node) {
2051 l = container_of(node, struct listener, conf.id);
2052 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
Willy Tarreau88500de2012-09-13 19:34:38 +02002053 file, linenum, l->luid, args[1], l->bind_conf->file, l->bind_conf->line);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
2055 goto out;
2056 }
2057 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
2058
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002059 cur_arg += 2;
2060 continue;
2061 }
2062
Emeric Bruned760922010-10-22 17:59:25 +02002063 if (!strcmp(args[cur_arg], "mode")) {
2064
2065 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2066 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2067 file, linenum, args[0], args[cur_arg]);
2068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
2070 }
2071
2072 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
2073
2074 cur_arg += 2;
2075 continue;
2076 }
2077
2078 if (!strcmp(args[cur_arg], "uid")) {
2079
2080 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2081 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2082 file, linenum, args[0], args[cur_arg]);
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
2086
2087 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
2088 cur_arg += 2;
2089 continue;
2090 }
2091
2092 if (!strcmp(args[cur_arg], "gid")) {
2093
2094 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2095 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2096 file, linenum, args[0], args[cur_arg]);
2097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
2100
2101 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2102 cur_arg += 2;
2103 continue;
2104 }
2105
2106 if (!strcmp(args[cur_arg], "user")) {
2107 struct passwd *user;
2108
2109 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2110 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2111 file, linenum, args[0], args[cur_arg]);
2112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
2114 }
2115 user = getpwnam(args[cur_arg + 1]);
2116 if (!user) {
2117 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2118 file, linenum, args[0], args[cur_arg + 1 ]);
2119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
2121 }
2122
2123 curproxy->listen->perm.ux.uid = user->pw_uid;
2124 cur_arg += 2;
2125 continue;
2126 }
2127
2128 if (!strcmp(args[cur_arg], "group")) {
2129 struct group *group;
2130
2131 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2132 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2133 file, linenum, args[0], args[cur_arg]);
2134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
2136 }
2137 group = getgrnam(args[cur_arg + 1]);
2138 if (!group) {
2139 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2140 file, linenum, args[0], args[cur_arg + 1 ]);
2141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
2143 }
2144
2145 curproxy->listen->perm.ux.gid = group->gr_gid;
2146 cur_arg += 2;
2147 continue;
2148 }
2149
Willy Tarreaub48f9582011-09-05 01:17:06 +02002150 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 +01002151 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002154 }
Willy Tarreau93893792009-07-23 13:19:11 +02002155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 }
2157 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2158 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2159 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2160 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002164 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002166
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 /* flush useless bits */
2168 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002171 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002172 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002174
Willy Tarreau1c47f852006-07-09 08:22:27 +02002175 if (!*args[1]) {
2176 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2177 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002180 }
2181
Willy Tarreaua534fea2008-08-03 12:19:50 +02002182 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002183 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002184 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002185 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002186 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2187
Willy Tarreau93893792009-07-23 13:19:11 +02002188 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2191 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2192 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2193 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2194 else {
2195 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
2199 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002200 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002201 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002202
2203 if (curproxy == &defproxy) {
2204 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002208 }
2209
2210 if (!*args[1]) {
2211 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2212 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002215 }
2216
2217 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002218 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002219
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002220 if (curproxy->uuid <= 0) {
2221 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002222 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002225 }
2226
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002227 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2228 if (node) {
2229 struct proxy *target = container_of(node, struct proxy, conf.id);
2230 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2231 file, linenum, proxy_type_str(curproxy), curproxy->id,
2232 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002237 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002238 else if (!strcmp(args[0], "description")) {
2239 int i, len=0;
2240 char *d;
2241
Cyril Bonté99ed3272010-01-24 23:29:44 +01002242 if (curproxy == &defproxy) {
2243 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2244 file, linenum, args[0]);
2245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
2247 }
2248
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002249 if (!*args[1]) {
2250 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2251 file, linenum, args[0]);
2252 return -1;
2253 }
2254
2255 for(i=1; *args[i]; i++)
2256 len += strlen(args[i])+1;
2257
2258 d = (char *)calloc(1, len);
2259 curproxy->desc = d;
2260
2261 d += sprintf(d, "%s", args[1]);
2262 for(i=2; *args[i]; i++)
2263 d += sprintf(d, " %s", args[i]);
2264
2265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2267 curproxy->state = PR_STSTOPPED;
2268 }
2269 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2270 curproxy->state = PR_STNEW;
2271 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002272 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2273 int cur_arg = 1;
2274 unsigned int set = 0;
2275
2276 while (*args[cur_arg]) {
2277 int u;
2278 if (strcmp(args[cur_arg], "all") == 0) {
2279 set = 0;
2280 break;
2281 }
2282 else if (strcmp(args[cur_arg], "odd") == 0) {
2283 set |= 0x55555555;
2284 }
2285 else if (strcmp(args[cur_arg], "even") == 0) {
2286 set |= 0xAAAAAAAA;
2287 }
2288 else {
2289 u = str2uic(args[cur_arg]);
2290 if (u < 1 || u > 32) {
2291 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2292 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002295 }
2296 if (u > global.nbproc) {
2297 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002300 }
2301 set |= 1 << (u - 1);
2302 }
2303 cur_arg++;
2304 }
2305 curproxy->bind_proc = set;
2306 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002307 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002308 if (curproxy == &defproxy) {
2309 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002312 }
2313
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002314 err = invalid_char(args[1]);
2315 if (err) {
2316 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2317 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002319 }
2320
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002321 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2322 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2323 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002326 }
2327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2329 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 if (*(args[1]) == 0) {
2335 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002340
Willy Tarreau67402132012-05-31 20:40:20 +02002341 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002342 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002343 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002344 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 curproxy->cookie_name = strdup(args[1]);
2346 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002347
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 cur_arg = 2;
2349 while (*(args[cur_arg])) {
2350 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002351 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 }
2353 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002354 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
2356 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002357 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
2359 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002360 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002363 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002365 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002366 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002367 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002369 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002371 else if (!strcmp(args[cur_arg], "httponly")) {
2372 curproxy->ck_opts |= PR_CK_HTTPONLY;
2373 }
2374 else if (!strcmp(args[cur_arg], "secure")) {
2375 curproxy->ck_opts |= PR_CK_SECURE;
2376 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002377 else if (!strcmp(args[cur_arg], "domain")) {
2378 if (!*args[cur_arg + 1]) {
2379 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2380 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002383 }
2384
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002385 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002386 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002387 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2388 " dots nor does not start with a dot."
2389 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002390 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002391 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002392 }
2393
2394 err = invalid_domainchar(args[cur_arg + 1]);
2395 if (err) {
2396 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2397 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002400 }
2401
Willy Tarreau68a897b2009-12-03 23:28:34 +01002402 if (!curproxy->cookie_domain) {
2403 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2404 } else {
2405 /* one domain was already specified, add another one by
2406 * building the string which will be returned along with
2407 * the cookie.
2408 */
2409 char *new_ptr;
2410 int new_len = strlen(curproxy->cookie_domain) +
2411 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2412 new_ptr = malloc(new_len);
2413 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2414 free(curproxy->cookie_domain);
2415 curproxy->cookie_domain = new_ptr;
2416 }
Willy Tarreau31936852010-10-06 16:59:56 +02002417 cur_arg++;
2418 }
2419 else if (!strcmp(args[cur_arg], "maxidle")) {
2420 unsigned int maxidle;
2421 const char *res;
2422
2423 if (!*args[cur_arg + 1]) {
2424 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2425 file, linenum, args[cur_arg]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2431 if (res) {
2432 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2433 file, linenum, *res, args[cur_arg]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437 curproxy->cookie_maxidle = maxidle;
2438 cur_arg++;
2439 }
2440 else if (!strcmp(args[cur_arg], "maxlife")) {
2441 unsigned int maxlife;
2442 const char *res;
2443
2444 if (!*args[cur_arg + 1]) {
2445 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2446 file, linenum, args[cur_arg]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
2451 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2452 if (res) {
2453 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2454 file, linenum, *res, args[cur_arg]);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002459 cur_arg++;
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002462 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 +02002463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
2467 cur_arg++;
2468 }
Willy Tarreau67402132012-05-31 20:40:20 +02002469 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2471 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
2474
Willy Tarreau67402132012-05-31 20:40:20 +02002475 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2477 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002480
Willy Tarreau67402132012-05-31 20:40:20 +02002481 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002482 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2483 file, linenum);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002487 else if (!strcmp(args[0], "persist")) { /* persist */
2488 if (*(args[1]) == 0) {
2489 Alert("parsing [%s:%d] : missing persist method.\n",
2490 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002493 }
2494
2495 if (!strncmp(args[1], "rdp-cookie", 10)) {
2496 curproxy->options2 |= PR_O2_RDPC_PRST;
2497
Emeric Brunb982a3d2010-01-04 15:45:53 +01002498 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002499 const char *beg, *end;
2500
2501 beg = args[1] + 11;
2502 end = strchr(beg, ')');
2503
2504 if (!end || end == beg) {
2505 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2506 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002509 }
2510
2511 free(curproxy->rdp_cookie_name);
2512 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2513 curproxy->rdp_cookie_len = end-beg;
2514 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002515 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002516 free(curproxy->rdp_cookie_name);
2517 curproxy->rdp_cookie_name = strdup("msts");
2518 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2519 }
2520 else { /* syntax */
2521 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2522 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002525 }
2526 }
2527 else {
2528 Alert("parsing [%s:%d] : unknown persist method.\n",
2529 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002532 }
2533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002535 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
Willy Tarreau977b8e42006-12-29 14:19:17 +01002543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002545
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002547 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 }
2552 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002553 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 curproxy->appsession_name = strdup(args[1]);
2555 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2556 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002557 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2558 if (err) {
2559 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2560 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002563 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002564 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002565
Willy Tarreau51041c72007-09-09 21:56:53 +02002566 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_ABORT;
2569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002571
2572 cur_arg = 6;
2573 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002574 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2575 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002576 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002577 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002578 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002579 } else if (!strcmp(args[cur_arg], "prefix")) {
2580 curproxy->options2 |= PR_O2_AS_PFX;
2581 } else if (!strcmp(args[cur_arg], "mode")) {
2582 if (!*args[cur_arg + 1]) {
2583 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2584 file, linenum, args[0], args[cur_arg]);
2585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
2587 }
2588
2589 cur_arg++;
2590 if (!strcmp(args[cur_arg], "query-string")) {
2591 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2592 curproxy->options2 |= PR_O2_AS_M_QS;
2593 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2594 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2595 curproxy->options2 |= PR_O2_AS_M_PP;
2596 } else {
2597 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
2600 }
2601 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002602 cur_arg++;
2603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 } /* Url App Session */
2605 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002606 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002610 if (curproxy == &defproxy) {
2611 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
2614 }
2615
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 if (*(args[4]) == 0) {
2617 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2618 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002622 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 curproxy->capture_name = strdup(args[2]);
2624 curproxy->capture_namelen = strlen(curproxy->capture_name);
2625 curproxy->capture_len = atol(args[4]);
2626 if (curproxy->capture_len >= CAPTURE_LEN) {
2627 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2628 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 curproxy->capture_len = CAPTURE_LEN - 1;
2631 }
2632 curproxy->to_log |= LW_COOKIE;
2633 }
2634 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2635 struct cap_hdr *hdr;
2636
2637 if (curproxy == &defproxy) {
2638 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 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 }
2642
2643 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2644 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2645 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002648 }
2649
2650 hdr = calloc(sizeof(struct cap_hdr), 1);
2651 hdr->next = curproxy->req_cap;
2652 hdr->name = strdup(args[3]);
2653 hdr->namelen = strlen(args[3]);
2654 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002655 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 hdr->index = curproxy->nb_req_cap++;
2657 curproxy->req_cap = hdr;
2658 curproxy->to_log |= LW_REQHDR;
2659 }
2660 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2661 struct cap_hdr *hdr;
2662
2663 if (curproxy == &defproxy) {
2664 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 +02002665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 }
2668
2669 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2670 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2671 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 }
2675 hdr = calloc(sizeof(struct cap_hdr), 1);
2676 hdr->next = curproxy->rsp_cap;
2677 hdr->name = strdup(args[3]);
2678 hdr->namelen = strlen(args[3]);
2679 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002680 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681 hdr->index = curproxy->nb_rsp_cap++;
2682 curproxy->rsp_cap = hdr;
2683 curproxy->to_log |= LW_RSPHDR;
2684 }
2685 else {
2686 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
2691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002695
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 if (*(args[1]) == 0) {
2697 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
2702 curproxy->conn_retries = atol(args[1]);
2703 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002704 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002705 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002706
2707 if (curproxy == &defproxy) {
2708 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
2711 }
2712
Willy Tarreauff011f22011-01-06 17:51:27 +01002713 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 +01002714 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2715 file, linenum, args[0]);
2716 err_code |= ERR_WARN;
2717 }
2718
Willy Tarreauff011f22011-01-06 17:51:27 +01002719 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002720
Willy Tarreauff011f22011-01-06 17:51:27 +01002721 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002722 err_code |= ERR_ALERT | ERR_ABORT;
2723 goto out;
2724 }
2725
Willy Tarreauff011f22011-01-06 17:51:27 +01002726 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2727 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002728 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002729 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2730 /* set the header name and length into the proxy structure */
2731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2732 err_code |= ERR_WARN;
2733
2734 if (!*args[1]) {
2735 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2736 file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 /* set the desired header name */
2742 free(curproxy->server_id_hdr_name);
2743 curproxy->server_id_hdr_name = strdup(args[1]);
2744 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2745 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002746 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002747 if (curproxy == &defproxy) {
2748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002751 }
2752
Willy Tarreauef6494c2010-01-28 17:12:36 +01002753 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002754 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2755 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002758 }
2759
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002760 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2761 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2762 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002765 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002766
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002767 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002768 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002769 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002770 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002771 struct redirect_rule *rule;
2772 int cur_arg;
2773 int type = REDIRECT_TYPE_NONE;
2774 int code = 302;
2775 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002776 char *cookie = NULL;
2777 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002778 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002779
Cyril Bonté99ed3272010-01-24 23:29:44 +01002780 if (curproxy == &defproxy) {
2781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002786 cur_arg = 1;
2787 while (*(args[cur_arg])) {
2788 if (!strcmp(args[cur_arg], "location")) {
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2791 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002794 }
2795
2796 type = REDIRECT_TYPE_LOCATION;
2797 cur_arg++;
2798 destination = args[cur_arg];
2799 }
2800 else if (!strcmp(args[cur_arg], "prefix")) {
2801 if (!*args[cur_arg + 1]) {
2802 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2803 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002806 }
2807
2808 type = REDIRECT_TYPE_PREFIX;
2809 cur_arg++;
2810 destination = args[cur_arg];
2811 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002812 else if (!strcmp(args[cur_arg], "scheme")) {
2813 if (!*args[cur_arg + 1]) {
2814 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2815 file, linenum, args[0], args[cur_arg]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819
2820 type = REDIRECT_TYPE_SCHEME;
2821 cur_arg++;
2822 destination = args[cur_arg];
2823 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002824 else if (!strcmp(args[cur_arg], "set-cookie")) {
2825 if (!*args[cur_arg + 1]) {
2826 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2827 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002830 }
2831
2832 cur_arg++;
2833 cookie = args[cur_arg];
2834 cookie_set = 1;
2835 }
2836 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2837 if (!*args[cur_arg + 1]) {
2838 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2839 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002842 }
2843
2844 cur_arg++;
2845 cookie = args[cur_arg];
2846 cookie_set = 0;
2847 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002848 else if (!strcmp(args[cur_arg],"code")) {
2849 if (!*args[cur_arg + 1]) {
2850 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002854 }
2855 cur_arg++;
2856 code = atol(args[cur_arg]);
2857 if (code < 301 || code > 303) {
2858 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2859 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002862 }
2863 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002864 else if (!strcmp(args[cur_arg],"drop-query")) {
2865 flags |= REDIRECT_FLAG_DROP_QS;
2866 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002867 else if (!strcmp(args[cur_arg],"append-slash")) {
2868 flags |= REDIRECT_FLAG_APPEND_SLASH;
2869 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002870 else if (strcmp(args[cur_arg], "if") == 0 ||
2871 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002872 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002873 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002874 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2875 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002879 break;
2880 }
2881 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002882 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002883 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002886 }
2887 cur_arg++;
2888 }
2889
2890 if (type == REDIRECT_TYPE_NONE) {
2891 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002895 }
2896
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002897 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2898 rule->cond = cond;
2899 rule->rdr_str = strdup(destination);
2900 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002901 if (cookie) {
2902 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002903 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002904 */
2905 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002906 if (cookie_set) {
2907 rule->cookie_str = malloc(rule->cookie_len + 10);
2908 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2909 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2910 rule->cookie_len += 9;
2911 } else {
2912 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002913 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002914 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2915 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002916 }
2917 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002918 rule->type = type;
2919 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002920 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002921 LIST_INIT(&rule->list);
2922 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002923 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2924 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002925 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002926 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002927 struct switching_rule *rule;
2928
Willy Tarreaub099aca2008-10-12 17:26:37 +02002929 if (curproxy == &defproxy) {
2930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002933 }
2934
Willy Tarreau55ea7572007-06-17 19:56:27 +02002935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002937
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002942 }
2943
Willy Tarreauef6494c2010-01-28 17:12:36 +01002944 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002945 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002949 }
2950
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002951 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2952 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2953 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002956 }
2957
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002958 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002959
Willy Tarreau55ea7572007-06-17 19:56:27 +02002960 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2961 rule->cond = cond;
2962 rule->be.name = strdup(args[1]);
2963 LIST_INIT(&rule->list);
2964 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2965 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002966 else if (strcmp(args[0], "use-server") == 0) {
2967 struct server_rule *rule;
2968
2969 if (curproxy == &defproxy) {
2970 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974
2975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2976 err_code |= ERR_WARN;
2977
2978 if (*(args[1]) == 0) {
2979 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983
2984 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2985 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2986 file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2992 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2993 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
2998 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2999
3000 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3001 rule->cond = cond;
3002 rule->srv.name = strdup(args[1]);
3003 LIST_INIT(&rule->list);
3004 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3005 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3006 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003007 else if ((!strcmp(args[0], "force-persist")) ||
3008 (!strcmp(args[0], "ignore-persist"))) {
3009 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003010
3011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
3017 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3018 err_code |= ERR_WARN;
3019
Willy Tarreauef6494c2010-01-28 17:12:36 +01003020 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003021 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3022 file, linenum, args[0]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003027 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3028 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3029 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003034 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003035
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003036 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003037 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003038 if (!strcmp(args[0], "force-persist")) {
3039 rule->type = PERSIST_TYPE_FORCE;
3040 } else {
3041 rule->type = PERSIST_TYPE_IGNORE;
3042 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003043 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003044 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003045 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003046 else if (!strcmp(args[0], "stick-table")) {
3047 int myidx = 1;
3048
Emeric Brun32da3c42010-09-23 18:39:19 +02003049 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003050 curproxy->table.type = (unsigned int)-1;
3051 while (*args[myidx]) {
3052 const char *err;
3053
3054 if (strcmp(args[myidx], "size") == 0) {
3055 myidx++;
3056 if (!*(args[myidx])) {
3057 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3058 file, linenum, args[myidx-1]);
3059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
3061 }
3062 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3063 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3064 file, linenum, *err, args[myidx-1]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003068 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003070 else if (strcmp(args[myidx], "peers") == 0) {
3071 myidx++;
3072 if (!*(args[myidx])) {
3073 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3074 file, linenum, args[myidx-1]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078 curproxy->table.peers.name = strdup(args[myidx++]);
3079 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 else if (strcmp(args[myidx], "expire") == 0) {
3081 myidx++;
3082 if (!*(args[myidx])) {
3083 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3084 file, linenum, args[myidx-1]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
3088 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3089 if (err) {
3090 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3091 file, linenum, *err, args[myidx-1]);
3092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
3094 }
3095 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003096 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003097 }
3098 else if (strcmp(args[myidx], "nopurge") == 0) {
3099 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003100 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003101 }
3102 else if (strcmp(args[myidx], "type") == 0) {
3103 myidx++;
3104 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3105 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3106 file, linenum, args[myidx]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003110 /* myidx already points to next arg */
3111 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003112 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003113 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003114 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003115
3116 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003117 nw = args[myidx];
3118 while (*nw) {
3119 /* the "store" keyword supports a comma-separated list */
3120 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003121 sa = NULL; /* store arg */
3122 while (*nw && *nw != ',') {
3123 if (*nw == '(') {
3124 *nw = 0;
3125 sa = ++nw;
3126 while (*nw != ')') {
3127 if (!*nw) {
3128 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3129 file, linenum, args[0], cw);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133 nw++;
3134 }
3135 *nw = '\0';
3136 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003137 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003138 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003139 if (*nw)
3140 *nw++ = '\0';
3141 type = stktable_get_data_type(cw);
3142 if (type < 0) {
3143 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3144 file, linenum, args[0], cw);
3145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
3147 }
Willy Tarreauac782882010-06-20 10:41:54 +02003148
3149 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3150 switch (err) {
3151 case PE_NONE: break;
3152 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003153 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3154 file, linenum, args[0], cw);
3155 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003156 break;
3157
3158 case PE_ARG_MISSING:
3159 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3160 file, linenum, args[0], cw);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163
3164 case PE_ARG_NOT_USED:
3165 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3166 file, linenum, args[0], cw);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169
3170 default:
3171 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3172 file, linenum, args[0], cw);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003175 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003176 }
3177 myidx++;
3178 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003179 else {
3180 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3181 file, linenum, args[myidx]);
3182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003184 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003185 }
3186
3187 if (!curproxy->table.size) {
3188 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3189 file, linenum);
3190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
3192 }
3193
3194 if (curproxy->table.type == (unsigned int)-1) {
3195 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3196 file, linenum);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
3200 }
3201 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003202 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003203 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003204 int myidx = 0;
3205 const char *name = NULL;
3206 int flags;
3207
3208 if (curproxy == &defproxy) {
3209 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
3214 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3215 err_code |= ERR_WARN;
3216 goto out;
3217 }
3218
3219 myidx++;
3220 if ((strcmp(args[myidx], "store") == 0) ||
3221 (strcmp(args[myidx], "store-request") == 0)) {
3222 myidx++;
3223 flags = STK_IS_STORE;
3224 }
3225 else if (strcmp(args[myidx], "store-response") == 0) {
3226 myidx++;
3227 flags = STK_IS_STORE | STK_ON_RSP;
3228 }
3229 else if (strcmp(args[myidx], "match") == 0) {
3230 myidx++;
3231 flags = STK_IS_MATCH;
3232 }
3233 else if (strcmp(args[myidx], "on") == 0) {
3234 myidx++;
3235 flags = STK_IS_MATCH | STK_IS_STORE;
3236 }
3237 else {
3238 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
3242
3243 if (*(args[myidx]) == 0) {
3244 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248
David du Colombier7af46052012-05-16 14:16:48 +02003249 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003250 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003251 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
3254 }
3255
3256 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003257 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003258 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3259 file, linenum, args[0], expr->fetch->kw);
3260 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003261 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 goto out;
3263 }
3264 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003265 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003266 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3267 file, linenum, args[0], expr->fetch->kw);
3268 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003269 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003270 goto out;
3271 }
3272 }
3273
3274 if (strcmp(args[myidx], "table") == 0) {
3275 myidx++;
3276 name = args[myidx++];
3277 }
3278
Willy Tarreauef6494c2010-01-28 17:12:36 +01003279 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003280 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3281 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3282 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003283 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003284 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003285 goto out;
3286 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003287 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003288 else if (*(args[myidx])) {
3289 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3290 file, linenum, args[0], args[myidx]);
3291 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003292 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003293 goto out;
3294 }
Emeric Brun97679e72010-09-23 17:56:44 +02003295 if (flags & STK_ON_RSP)
3296 err_code |= warnif_cond_requires_req(cond, file, linenum);
3297 else
3298 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003299
Emeric Brunb982a3d2010-01-04 15:45:53 +01003300 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3301 rule->cond = cond;
3302 rule->expr = expr;
3303 rule->flags = flags;
3304 rule->table.name = name ? strdup(name) : NULL;
3305 LIST_INIT(&rule->list);
3306 if (flags & STK_ON_RSP)
3307 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3308 else
3309 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003314
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3316 curproxy->uri_auth = NULL; /* we must detach from the default config */
3317
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003318 if (!*args[1]) {
3319 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003320 } else if (!strcmp(args[1], "admin")) {
3321 struct stats_admin_rule *rule;
3322
3323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
3329 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3330 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3331 err_code |= ERR_ALERT | ERR_ABORT;
3332 goto out;
3333 }
3334
3335 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3336 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3337 file, linenum, args[0], args[1]);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003341 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3342 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3343 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346 }
3347
3348 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3349
3350 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3351 rule->cond = cond;
3352 LIST_INIT(&rule->list);
3353 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 } else if (!strcmp(args[1], "uri")) {
3355 if (*(args[2]) == 0) {
3356 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3360 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_ABORT;
3362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364 } else if (!strcmp(args[1], "realm")) {
3365 if (*(args[2]) == 0) {
3366 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3370 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_ABORT;
3372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003374 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003375 unsigned interval;
3376
3377 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3378 if (err) {
3379 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3380 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003383 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3384 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_ABORT;
3386 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003387 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003388 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003389 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003390
3391 if (curproxy == &defproxy) {
3392 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396
3397 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3398 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3399 err_code |= ERR_ALERT | ERR_ABORT;
3400 goto out;
3401 }
3402
Willy Tarreauff011f22011-01-06 17:51:27 +01003403 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3404 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003405 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3406 file, linenum, args[0]);
3407 err_code |= ERR_WARN;
3408 }
3409
Willy Tarreauff011f22011-01-06 17:51:27 +01003410 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003411
Willy Tarreauff011f22011-01-06 17:51:27 +01003412 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003413 err_code |= ERR_ALERT | ERR_ABORT;
3414 goto out;
3415 }
3416
Willy Tarreauff011f22011-01-06 17:51:27 +01003417 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3418 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003419
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 } else if (!strcmp(args[1], "auth")) {
3421 if (*(args[2]) == 0) {
3422 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_ALERT | ERR_FATAL;
3424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3426 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_ALERT | ERR_ABORT;
3428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
3430 } else if (!strcmp(args[1], "scope")) {
3431 if (*(args[2]) == 0) {
3432 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3436 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003437 err_code |= ERR_ALERT | ERR_ABORT;
3438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 }
3440 } else if (!strcmp(args[1], "enable")) {
3441 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_ABORT;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003446 } else if (!strcmp(args[1], "hide-version")) {
3447 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3448 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_ABORT;
3450 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003451 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003452 } else if (!strcmp(args[1], "show-legends")) {
3453 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3455 err_code |= ERR_ALERT | ERR_ABORT;
3456 goto out;
3457 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003458 } else if (!strcmp(args[1], "show-node")) {
3459
3460 if (*args[2]) {
3461 int i;
3462 char c;
3463
3464 for (i=0; args[2][i]; i++) {
3465 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003466 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3467 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003468 break;
3469 }
3470
3471 if (!i || args[2][i]) {
3472 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3473 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3474 file, linenum, args[0], args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 }
3479
3480 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3481 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3482 err_code |= ERR_ALERT | ERR_ABORT;
3483 goto out;
3484 }
3485 } else if (!strcmp(args[1], "show-desc")) {
3486 char *desc = NULL;
3487
3488 if (*args[2]) {
3489 int i, len=0;
3490 char *d;
3491
3492 for(i=2; *args[i]; i++)
3493 len += strlen(args[i])+1;
3494
3495 desc = d = (char *)calloc(1, len);
3496
3497 d += sprintf(d, "%s", args[2]);
3498 for(i=3; *args[i]; i++)
3499 d += sprintf(d, " %s", args[i]);
3500 }
3501
3502 if (!*args[2] && !global.desc)
3503 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3504 file, linenum, args[1]);
3505 else {
3506 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3507 free(desc);
3508 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3509 err_code |= ERR_ALERT | ERR_ABORT;
3510 goto out;
3511 }
3512 free(desc);
3513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003515stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003516 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 +01003517 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 }
3521 }
3522 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003523 int optnum;
3524
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003525 if (*(args[1]) == '\0') {
3526 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3527 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003531
3532 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3533 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003534 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3535 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3536 file, linenum, cfg_opts[optnum].name);
3537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
3539 }
Willy Tarreau93893792009-07-23 13:19:11 +02003540 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3541 err_code |= ERR_WARN;
3542 goto out;
3543 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003544
Willy Tarreau3842f002009-06-14 11:39:52 +02003545 curproxy->no_options &= ~cfg_opts[optnum].val;
3546 curproxy->options &= ~cfg_opts[optnum].val;
3547
3548 switch (kwm) {
3549 case KWM_STD:
3550 curproxy->options |= cfg_opts[optnum].val;
3551 break;
3552 case KWM_NO:
3553 curproxy->no_options |= cfg_opts[optnum].val;
3554 break;
3555 case KWM_DEF: /* already cleared */
3556 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003557 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003558
Willy Tarreau93893792009-07-23 13:19:11 +02003559 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003560 }
3561 }
3562
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003563 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3564 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003565 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3566 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3567 file, linenum, cfg_opts2[optnum].name);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
Willy Tarreau93893792009-07-23 13:19:11 +02003571 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3572 err_code |= ERR_WARN;
3573 goto out;
3574 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003575
Willy Tarreau3842f002009-06-14 11:39:52 +02003576 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3577 curproxy->options2 &= ~cfg_opts2[optnum].val;
3578
3579 switch (kwm) {
3580 case KWM_STD:
3581 curproxy->options2 |= cfg_opts2[optnum].val;
3582 break;
3583 case KWM_NO:
3584 curproxy->no_options2 |= cfg_opts2[optnum].val;
3585 break;
3586 case KWM_DEF: /* already cleared */
3587 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003588 }
Willy Tarreau93893792009-07-23 13:19:11 +02003589 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003590 }
3591 }
3592
Willy Tarreau3842f002009-06-14 11:39:52 +02003593 if (kwm != KWM_STD) {
3594 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003595 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003598 }
3599
Emeric Brun3a058f32009-06-30 18:26:00 +02003600 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003601 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003603 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003604 if (*(args[2]) != '\0') {
3605 if (!strcmp(args[2], "clf")) {
3606 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003607 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003608 } else {
3609 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003612 }
3613 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003614 if (curproxy->logformat_string != default_http_log_format &&
3615 curproxy->logformat_string != default_tcp_log_format &&
3616 curproxy->logformat_string != clf_http_log_format)
3617 free(curproxy->logformat_string);
3618 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003619 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003620 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003622 if (curproxy->logformat_string != default_http_log_format &&
3623 curproxy->logformat_string != default_tcp_log_format &&
3624 curproxy->logformat_string != clf_http_log_format)
3625 free(curproxy->logformat_string);
3626 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 else if (!strcmp(args[1], "tcpka")) {
3629 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003630 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003632
3633 if (curproxy->cap & PR_CAP_FE)
3634 curproxy->options |= PR_O_TCP_CLI_KA;
3635 if (curproxy->cap & PR_CAP_BE)
3636 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 }
3638 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_WARN;
3641
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003643 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003644 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003645 curproxy->options2 &= ~PR_O2_CHK_ANY;
3646 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 if (!*args[2]) { /* no argument */
3648 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3649 curproxy->check_len = strlen(DEF_CHECK_REQ);
3650 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003651 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003652 curproxy->check_req = (char *)malloc(reqlen);
3653 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003654 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003656 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 if (*args[4])
3658 reqlen += strlen(args[4]);
3659 else
3660 reqlen += strlen("HTTP/1.0");
3661
3662 curproxy->check_req = (char *)malloc(reqlen);
3663 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003664 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003665 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003666 }
3667 else if (!strcmp(args[1], "ssl-hello-chk")) {
3668 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003669 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003671
Willy Tarreaua534fea2008-08-03 12:19:50 +02003672 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003673 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003674 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003675 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
Willy Tarreau23677902007-05-08 23:50:35 +02003677 else if (!strcmp(args[1], "smtpchk")) {
3678 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003679 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003680 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003681 curproxy->options2 &= ~PR_O2_CHK_ANY;
3682 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003683
3684 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3685 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3686 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3687 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3688 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3689 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3690 curproxy->check_req = (char *)malloc(reqlen);
3691 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3692 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3693 } else {
3694 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3695 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3696 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3697 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3698 }
3699 }
3700 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003701 else if (!strcmp(args[1], "pgsql-check")) {
3702 /* use PostgreSQL request to check servers' health */
3703 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3704 err_code |= ERR_WARN;
3705
3706 free(curproxy->check_req);
3707 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003708 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003709 curproxy->options2 |= PR_O2_PGSQL_CHK;
3710
3711 if (*(args[2])) {
3712 int cur_arg = 2;
3713
3714 while (*(args[cur_arg])) {
3715 if (strcmp(args[cur_arg], "user") == 0) {
3716 char * packet;
3717 uint32_t packet_len;
3718 uint32_t pv;
3719
3720 /* suboption header - needs additional argument for it */
3721 if (*(args[cur_arg+1]) == 0) {
3722 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3723 file, linenum, args[0], args[1], args[cur_arg]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727
3728 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3729 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3730 pv = htonl(0x30000); /* protocol version 3.0 */
3731
3732 packet = (char*) calloc(1, packet_len);
3733
3734 memcpy(packet + 4, &pv, 4);
3735
3736 /* copy "user" */
3737 memcpy(packet + 8, "user", 4);
3738
3739 /* copy username */
3740 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3741
3742 free(curproxy->check_req);
3743 curproxy->check_req = packet;
3744 curproxy->check_len = packet_len;
3745
3746 packet_len = htonl(packet_len);
3747 memcpy(packet, &packet_len, 4);
3748 cur_arg += 2;
3749 } else {
3750 /* unknown suboption - catchall */
3751 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3752 file, linenum, args[0], args[1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756 } /* end while loop */
3757 }
3758 }
3759
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003760 else if (!strcmp(args[1], "redis-check")) {
3761 /* use REDIS PING request to check servers' health */
3762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3763 err_code |= ERR_WARN;
3764
3765 free(curproxy->check_req);
3766 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003767 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003768 curproxy->options2 |= PR_O2_REDIS_CHK;
3769
3770 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3771 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3772 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3773 }
3774
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003775 else if (!strcmp(args[1], "mysql-check")) {
3776 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003777 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3778 err_code |= ERR_WARN;
3779
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003780 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003781 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003782 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003783 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003784
3785 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3786 * const char mysql40_client_auth_pkt[] = {
3787 * "\x0e\x00\x00" // packet length
3788 * "\x01" // packet number
3789 * "\x00\x00" // client capabilities
3790 * "\x00\x00\x01" // max packet
3791 * "haproxy\x00" // username (null terminated string)
3792 * "\x00" // filler (always 0x00)
3793 * "\x01\x00\x00" // packet length
3794 * "\x00" // packet number
3795 * "\x01" // COM_QUIT command
3796 * };
3797 */
3798
3799 if (*(args[2])) {
3800 int cur_arg = 2;
3801
3802 while (*(args[cur_arg])) {
3803 if (strcmp(args[cur_arg], "user") == 0) {
3804 char *mysqluser;
3805 int packetlen, reqlen, userlen;
3806
3807 /* suboption header - needs additional argument for it */
3808 if (*(args[cur_arg+1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3810 file, linenum, args[0], args[1], args[cur_arg]);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814 mysqluser = args[cur_arg + 1];
3815 userlen = strlen(mysqluser);
3816 packetlen = userlen + 7;
3817 reqlen = packetlen + 9;
3818
3819 free(curproxy->check_req);
3820 curproxy->check_req = (char *)calloc(1, reqlen);
3821 curproxy->check_len = reqlen;
3822
3823 snprintf(curproxy->check_req, 4, "%c%c%c",
3824 ((unsigned char) packetlen & 0xff),
3825 ((unsigned char) (packetlen >> 8) & 0xff),
3826 ((unsigned char) (packetlen >> 16) & 0xff));
3827
3828 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003829 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003830 curproxy->check_req[8] = 1;
3831 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3832 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3833 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3834 cur_arg += 2;
3835 } else {
3836 /* unknown suboption - catchall */
3837 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3838 file, linenum, args[0], args[1]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 } /* end while loop */
3843 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003844 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003845 else if (!strcmp(args[1], "ldap-check")) {
3846 /* use LDAP request to check servers' health */
3847 free(curproxy->check_req);
3848 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003849 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003850 curproxy->options2 |= PR_O2_LDAP_CHK;
3851
3852 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3853 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3854 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3855 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003856 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003857 int cur_arg;
3858
3859 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3860 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003861 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003862
Willy Tarreau87cf5142011-08-19 22:57:24 +02003863 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003864
3865 free(curproxy->fwdfor_hdr_name);
3866 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3867 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3868
3869 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3870 cur_arg = 2;
3871 while (*(args[cur_arg])) {
3872 if (!strcmp(args[cur_arg], "except")) {
3873 /* suboption except - needs additional argument for it */
3874 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3875 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003879 }
3880 /* flush useless bits */
3881 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003882 cur_arg += 2;
3883 } else if (!strcmp(args[cur_arg], "header")) {
3884 /* suboption header - needs additional argument for it */
3885 if (*(args[cur_arg+1]) == 0) {
3886 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3887 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003890 }
3891 free(curproxy->fwdfor_hdr_name);
3892 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3893 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3894 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003895 } else if (!strcmp(args[cur_arg], "if-none")) {
3896 curproxy->options &= ~PR_O_FF_ALWAYS;
3897 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003898 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003899 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003900 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003901 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003904 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003905 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003906 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003907 else if (!strcmp(args[1], "originalto")) {
3908 int cur_arg;
3909
3910 /* insert x-original-to field, but not for the IP address listed as an except.
3911 * set default options (ie: bitfield, header name, etc)
3912 */
3913
3914 curproxy->options |= PR_O_ORGTO;
3915
3916 free(curproxy->orgto_hdr_name);
3917 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3918 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3919
Willy Tarreau87cf5142011-08-19 22:57:24 +02003920 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003921 cur_arg = 2;
3922 while (*(args[cur_arg])) {
3923 if (!strcmp(args[cur_arg], "except")) {
3924 /* suboption except - needs additional argument for it */
3925 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3926 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] 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 /* flush useless bits */
3932 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3933 cur_arg += 2;
3934 } else if (!strcmp(args[cur_arg], "header")) {
3935 /* suboption header - needs additional argument for it */
3936 if (*(args[cur_arg+1]) == 0) {
3937 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3938 file, linenum, args[0], args[1], args[cur_arg]);
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 free(curproxy->orgto_hdr_name);
3943 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3944 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3945 cur_arg += 2;
3946 } else {
3947 /* unknown suboption - catchall */
3948 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3949 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003952 }
3953 } /* end while loop */
3954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 else {
3956 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau93893792009-07-23 13:19:11 +02003960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003962 else if (!strcmp(args[0], "default_backend")) {
3963 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003965
3966 if (*(args[1]) == 0) {
3967 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003970 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003971 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003972 curproxy->defbe.name = strdup(args[1]);
3973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003975 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003977
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003978 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3979 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 /* enable reconnections to dispatch */
3982 curproxy->options |= PR_O_REDISP;
3983 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003984 else if (!strcmp(args[0], "http-check")) {
3985 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003987
3988 if (strcmp(args[1], "disable-on-404") == 0) {
3989 /* enable a graceful server shutdown on an HTTP 404 response */
3990 curproxy->options |= PR_O_DISABLE404;
3991 }
Willy Tarreauef781042010-01-27 11:53:01 +01003992 else if (strcmp(args[1], "send-state") == 0) {
3993 /* enable emission of the apparent state of a server in HTTP checks */
3994 curproxy->options2 |= PR_O2_CHK_SNDST;
3995 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003996 else if (strcmp(args[1], "expect") == 0) {
3997 const char *ptr_arg;
3998 int cur_arg;
3999
4000 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4001 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
4005
4006 cur_arg = 2;
4007 /* consider exclamation marks, sole or at the beginning of a word */
4008 while (*(ptr_arg = args[cur_arg])) {
4009 while (*ptr_arg == '!') {
4010 curproxy->options2 ^= PR_O2_EXP_INV;
4011 ptr_arg++;
4012 }
4013 if (*ptr_arg)
4014 break;
4015 cur_arg++;
4016 }
4017 /* now ptr_arg points to the beginning of a word past any possible
4018 * exclamation mark, and cur_arg is the argument which holds this word.
4019 */
4020 if (strcmp(ptr_arg, "status") == 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_STS;
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, "string") == 0) {
4032 if (!*(args[cur_arg + 1])) {
4033 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004039 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004040 curproxy->expect_str = strdup(args[cur_arg + 1]);
4041 }
4042 else if (strcmp(ptr_arg, "rstatus") == 0) {
4043 if (!*(args[cur_arg + 1])) {
4044 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4045 file, linenum, args[0], args[1], ptr_arg);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004050 free(curproxy->expect_str);
4051 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4052 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004053 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4054 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4055 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4056 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060 }
4061 else if (strcmp(ptr_arg, "rstring") == 0) {
4062 if (!*(args[cur_arg + 1])) {
4063 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4064 file, linenum, args[0], args[1], ptr_arg);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004069 free(curproxy->expect_str);
4070 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4071 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004072 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4073 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4074 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4075 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079 }
4080 else {
4081 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4082 file, linenum, args[0], args[1], ptr_arg);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004087 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004088 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 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004091 }
4092 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004093 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004094 if (curproxy == &defproxy) {
4095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004098 }
4099
Willy Tarreaub80c2302007-11-30 20:51:32 +01004100 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004101 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004102
4103 if (strcmp(args[1], "fail") == 0) {
4104 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004105 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004106 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4107 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004110 }
4111
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004112 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4113 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4114 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004117 }
4118 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4119 }
4120 else {
4121 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004124 }
4125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126#ifdef TPROXY
4127 else if (!strcmp(args[0], "transparent")) {
4128 /* enable transparent proxy connections */
4129 curproxy->options |= PR_O_TRANSP;
4130 }
4131#endif
4132 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004133 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004135
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 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 Tarreaubaaee002006-06-26 02:48:02 +02004140 }
4141 curproxy->maxconn = atol(args[1]);
4142 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004143 else if (!strcmp(args[0], "backlog")) { /* backlog */
4144 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004146
4147 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 Tarreauc73ce2b2008-01-06 10:55:10 +01004151 }
4152 curproxy->backlog = atol(args[1]);
4153 }
Willy Tarreau86034312006-12-29 00:10:33 +01004154 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004157
Willy Tarreau86034312006-12-29 00:10:33 +01004158 if (*(args[1]) == 0) {
4159 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004162 }
4163 curproxy->fullconn = atol(args[1]);
4164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4166 if (*(args[1]) == 0) {
4167 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004171 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4172 if (err) {
4173 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4174 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004177 }
4178 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 }
4180 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004181 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 if (curproxy == &defproxy) {
4183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004187 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004189
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 if (strchr(args[1], ':') == NULL) {
4191 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004195 sk = str2sa(args[1]);
4196 if (!sk) {
4197 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004202 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 }
4204 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004205 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004207
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004208 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4209 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004214 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4215 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4216 err_code |= ERR_WARN;
4217
4218 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4219 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4220 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4221 }
4222 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4223 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4224 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4225 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004226 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4227 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4228 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4229 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004230 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004231 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
4234 }
4235 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004236 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004238 char *rport, *raddr;
4239 short realport = 0;
4240 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004242 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_ALERT | ERR_FATAL;
4245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004247 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249
4250 if (!*args[2]) {
4251 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004256
4257 err = invalid_char(args[1]);
4258 if (err) {
4259 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4260 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004263 }
4264
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004265 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004266 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004267
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004268 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4270 err_code |= ERR_ALERT | ERR_ABORT;
4271 goto out;
4272 }
4273
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004274 /* the servers are linked backwards first */
4275 newsrv->next = curproxy->srv;
4276 curproxy->srv = newsrv;
4277 newsrv->proxy = curproxy;
4278 newsrv->conf.file = file;
4279 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280
Simon Hormanaf514952011-06-21 14:34:57 +09004281 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004282 LIST_INIT(&newsrv->pendconns);
4283 do_check = 0;
4284 newsrv->state = SRV_RUNNING; /* early server setup */
4285 newsrv->last_change = now.tv_sec;
4286 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004288 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004289 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004290 * - IP: => port=+0, relative
4291 * - IP:N => port=N, absolute
4292 * - IP:+N => port=+N, relative
4293 * - IP:-N => port=-N, relative
4294 */
4295 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004296 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004297 if (rport) {
4298 *rport++ = 0;
4299 realport = atol(rport);
4300 if (!isdigit((unsigned char)*rport))
4301 newsrv->state |= SRV_MAPPORTS;
4302 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004304
Willy Tarreaufab5a432011-03-04 15:31:53 +01004305 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004307 if (!sk) {
4308 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004313 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004314 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004315
4316 if (!sk) {
4317 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4318 file, linenum, newsrv->addr.ss_family, args[2]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004322 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004323
4324 newsrv->check_port = curproxy->defsrv.check_port;
4325 newsrv->inter = curproxy->defsrv.inter;
4326 newsrv->fastinter = curproxy->defsrv.fastinter;
4327 newsrv->downinter = curproxy->defsrv.downinter;
4328 newsrv->rise = curproxy->defsrv.rise;
4329 newsrv->fall = curproxy->defsrv.fall;
4330 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4331 newsrv->minconn = curproxy->defsrv.minconn;
4332 newsrv->maxconn = curproxy->defsrv.maxconn;
4333 newsrv->slowstart = curproxy->defsrv.slowstart;
4334 newsrv->onerror = curproxy->defsrv.onerror;
4335 newsrv->consecutive_errors_limit
4336 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004337#ifdef OPENSSL
4338 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4339#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004340 newsrv->uweight = newsrv->iweight
4341 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004343 newsrv->curfd = -1; /* no health-check in progress */
4344 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004346 cur_arg = 3;
4347 } else {
4348 newsrv = &curproxy->defsrv;
4349 cur_arg = 1;
4350 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004351
Willy Tarreaubaaee002006-06-26 02:48:02 +02004352 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004353 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004354 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004355
4356 if (!*args[cur_arg + 1]) {
4357 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4358 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004361 }
4362
4363 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004364 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004365
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004366 if (newsrv->puid <= 0) {
4367 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004368 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004371 }
4372
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004373 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4374 if (node) {
4375 struct server *target = container_of(node, struct server, conf.id);
4376 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4377 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
4381 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004382 cur_arg += 2;
4383 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004384 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 newsrv->cookie = strdup(args[cur_arg + 1]);
4386 newsrv->cklen = strlen(args[cur_arg + 1]);
4387 cur_arg += 2;
4388 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004389 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004390 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4391 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4392 cur_arg += 2;
4393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004395 if (!*args[cur_arg + 1]) {
4396 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4397 file, linenum, args[cur_arg]);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004403 if (newsrv->rise <= 0) {
4404 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4405 file, linenum, args[cur_arg]);
4406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
4408 }
4409
Willy Tarreau96839092010-03-29 10:02:24 +02004410 if (newsrv->health)
4411 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 cur_arg += 2;
4413 }
4414 else if (!strcmp(args[cur_arg], "fall")) {
4415 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004416
4417 if (!*args[cur_arg + 1]) {
4418 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4419 file, linenum, args[cur_arg]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423
4424 if (newsrv->fall <= 0) {
4425 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4426 file, linenum, args[cur_arg]);
4427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
4429 }
4430
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 cur_arg += 2;
4432 }
4433 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004434 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4435 if (err) {
4436 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4437 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004440 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004441 if (val <= 0) {
4442 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4443 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004446 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004447 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 cur_arg += 2;
4449 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004450 else if (!strcmp(args[cur_arg], "fastinter")) {
4451 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4452 if (err) {
4453 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4454 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004457 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004458 if (val <= 0) {
4459 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4460 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_ALERT | ERR_FATAL;
4462 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004463 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004464 newsrv->fastinter = val;
4465 cur_arg += 2;
4466 }
4467 else if (!strcmp(args[cur_arg], "downinter")) {
4468 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4469 if (err) {
4470 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4471 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004474 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004475 if (val <= 0) {
4476 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4477 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004480 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004481 newsrv->downinter = val;
4482 cur_arg += 2;
4483 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004484 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004485 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004486 if (!sk) {
4487 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
4491 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004492 cur_arg += 2;
4493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 else if (!strcmp(args[cur_arg], "port")) {
4495 newsrv->check_port = atol(args[cur_arg + 1]);
4496 cur_arg += 2;
4497 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004498 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 newsrv->state |= SRV_BACKUP;
4500 cur_arg ++;
4501 }
Simon Hormanfa461682011-06-25 09:39:49 +09004502 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4503 newsrv->state |= SRV_NON_STICK;
4504 cur_arg ++;
4505 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004506 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4507 newsrv->state |= SRV_SEND_PROXY;
4508 cur_arg ++;
4509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 else if (!strcmp(args[cur_arg], "weight")) {
4511 int w;
4512 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004513 if (w < 0 || w > 256) {
4514 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004519 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 cur_arg += 2;
4521 }
4522 else if (!strcmp(args[cur_arg], "minconn")) {
4523 newsrv->minconn = atol(args[cur_arg + 1]);
4524 cur_arg += 2;
4525 }
4526 else if (!strcmp(args[cur_arg], "maxconn")) {
4527 newsrv->maxconn = atol(args[cur_arg + 1]);
4528 cur_arg += 2;
4529 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004530 else if (!strcmp(args[cur_arg], "maxqueue")) {
4531 newsrv->maxqueue = atol(args[cur_arg + 1]);
4532 cur_arg += 2;
4533 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004534 else if (!strcmp(args[cur_arg], "slowstart")) {
4535 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004536 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004537 if (err) {
4538 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4539 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004542 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004543 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004544 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4545 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004548 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004549 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004550 cur_arg += 2;
4551 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004552 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004553
4554 if (!*args[cur_arg + 1]) {
4555 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4556 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004559 }
4560
4561 newsrv->trackit = strdup(args[cur_arg + 1]);
4562
4563 cur_arg += 2;
4564 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004565 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566 global.maxsock++;
4567 do_check = 1;
4568 cur_arg += 1;
4569 }
Willy Tarreau96839092010-03-29 10:02:24 +02004570 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4571 newsrv->state |= SRV_MAINTAIN;
4572 newsrv->state &= ~SRV_RUNNING;
4573 newsrv->health = 0;
4574 cur_arg += 1;
4575 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004576 else if (!strcmp(args[cur_arg], "ssl")) {
4577#ifdef USE_OPENSSL
4578 newsrv->use_ssl = 1;
4579 cur_arg += 1;
4580#else /* USE_OPENSSL */
4581 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4582 file, linenum, args[cur_arg]);
4583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
4585#endif /* USE_OPENSSL */
4586 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004587 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4588#ifdef USE_OPENSSL
4589 if (!*args[cur_arg + 1]) {
4590 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4591 file, linenum, args[0], args[cur_arg]);
4592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
4595
4596 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4597
4598 cur_arg += 2;
4599 continue;
4600#else
4601 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4602 file, linenum, args[0], args[cur_arg]);
4603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605#endif
4606 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004607 else if (!strcmp(args[cur_arg], "nosslv3")) {
4608#ifdef USE_OPENSSL
4609 newsrv->ssl_ctx.nosslv3 = 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 }
4618 else if (!strcmp(args[cur_arg], "notlsv1")) {
4619#ifdef USE_OPENSSL
4620 newsrv->ssl_ctx.notlsv1 = 1;
4621 cur_arg += 1;
4622#else /* USE_OPENSSL */
4623 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4624 file, linenum, args[cur_arg]);
4625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
4627#endif /* USE_OPENSSL */
4628 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004630 if (!strcmp(args[cur_arg + 1], "none"))
4631 newsrv->observe = HANA_OBS_NONE;
4632 else if (!strcmp(args[cur_arg + 1], "layer4"))
4633 newsrv->observe = HANA_OBS_LAYER4;
4634 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4635 if (curproxy->mode != PR_MODE_HTTP) {
4636 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4637 file, linenum, args[cur_arg + 1]);
4638 err_code |= ERR_ALERT;
4639 }
4640 newsrv->observe = HANA_OBS_LAYER7;
4641 }
4642 else {
4643 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004644 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004645 file, linenum, args[cur_arg], args[cur_arg + 1]);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649
4650 cur_arg += 2;
4651 }
4652 else if (!strcmp(args[cur_arg], "on-error")) {
4653 if (!strcmp(args[cur_arg + 1], "fastinter"))
4654 newsrv->onerror = HANA_ONERR_FASTINTER;
4655 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4656 newsrv->onerror = HANA_ONERR_FAILCHK;
4657 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4658 newsrv->onerror = HANA_ONERR_SUDDTH;
4659 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4660 newsrv->onerror = HANA_ONERR_MARKDWN;
4661 else {
4662 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004663 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004664 file, linenum, args[cur_arg], args[cur_arg + 1]);
4665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
4667 }
4668
4669 cur_arg += 2;
4670 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004671 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4672 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4673 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4674 else {
4675 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4676 file, linenum, args[cur_arg], args[cur_arg + 1]);
4677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
4679 }
4680
4681 cur_arg += 2;
4682 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004683 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4684 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4685 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4686 else {
4687 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4688 file, linenum, args[cur_arg], args[cur_arg + 1]);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
4692
4693 cur_arg += 2;
4694 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004695 else if (!strcmp(args[cur_arg], "error-limit")) {
4696 if (!*args[cur_arg + 1]) {
4697 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4698 file, linenum, args[cur_arg]);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
4702
4703 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4704
4705 if (newsrv->consecutive_errors_limit <= 0) {
4706 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4707 file, linenum, args[cur_arg]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004711 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004712 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004713 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004714 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004715 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004716
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004718#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004719 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004720 file, linenum, "source", "usesrc");
4721#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004722 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004724#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 }
4728 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004729 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4730 if (!sk) {
4731 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
4734 }
4735 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004736
4737 if (port_low != port_high) {
4738 int i;
4739 if (port_low <= 0 || port_low > 65535 ||
4740 port_high <= 0 || port_high > 65535 ||
4741 port_low > port_high) {
4742 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4743 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004746 }
4747 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4748 for (i = 0; i < newsrv->sport_range->size; i++)
4749 newsrv->sport_range->ports[i] = port_low + i;
4750 }
4751
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004753 while (*(args[cur_arg])) {
4754 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004755#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4756#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004757 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4758 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4759 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004762 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004763#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004764 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004765 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004766 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004769 }
4770 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004771 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004772 newsrv->state |= SRV_TPROXY_CLI;
4773 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004774 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004775 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004776 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4777 char *name, *end;
4778
4779 name = args[cur_arg+1] + 7;
4780 while (isspace(*name))
4781 name++;
4782
4783 end = name;
4784 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4785 end++;
4786
4787 newsrv->state &= ~SRV_TPROXY_MASK;
4788 newsrv->state |= SRV_TPROXY_DYN;
4789 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4790 newsrv->bind_hdr_len = end - name;
4791 memcpy(newsrv->bind_hdr_name, name, end - name);
4792 newsrv->bind_hdr_name[end-name] = '\0';
4793 newsrv->bind_hdr_occ = -1;
4794
4795 /* now look for an occurrence number */
4796 while (isspace(*end))
4797 end++;
4798 if (*end == ',') {
4799 end++;
4800 name = end;
4801 if (*end == '-')
4802 end++;
4803 while (isdigit(*end))
4804 end++;
4805 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4806 }
4807
4808 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4809 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4810 " occurrences values smaller than %d.\n",
4811 file, linenum, MAX_HDR_HISTORY);
4812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
4814 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004815 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004816 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004817 if (!sk) {
4818 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
4822 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004823 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004824 }
4825 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004826#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004827 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004828#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004829 cur_arg += 2;
4830 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004831#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004832 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004833 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004836#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4837 } /* "usesrc" */
4838
4839 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4840#ifdef SO_BINDTODEVICE
4841 if (!*args[cur_arg + 1]) {
4842 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004846 }
4847 if (newsrv->iface_name)
4848 free(newsrv->iface_name);
4849
4850 newsrv->iface_name = strdup(args[cur_arg + 1]);
4851 newsrv->iface_len = strlen(newsrv->iface_name);
4852 global.last_checks |= LSTCHK_NETADM;
4853#else
4854 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4855 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004858#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004859 cur_arg += 2;
4860 continue;
4861 }
4862 /* this keyword in not an option of "source" */
4863 break;
4864 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004866 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004867 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4868 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004873 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004874 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 +01004875 file, linenum, newsrv->id);
4876 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004877 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 +01004878 file, linenum);
4879
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
4883 }
4884
4885 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004886 if (newsrv->trackit) {
4887 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4888 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004891 }
4892
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004893 /* try to get the port from check_addr if check_port not set */
4894 if (!newsrv->check_port)
4895 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004896
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4898 newsrv->check_port = realport; /* by default */
4899 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004900 /* not yet valid, because no port was set on
4901 * the server either. We'll check if we have
4902 * a known port on the first listener.
4903 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004904 struct listener *l = curproxy->listen;
4905 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4906 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004907 }
4908 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4910 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004914
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004915 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004916 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004917 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4918 err_code |= ERR_ALERT | ERR_ABORT;
4919 goto out;
4920 }
4921
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004922 /* Allocate buffer for partial check results... */
4923 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4924 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4925 err_code |= ERR_ALERT | ERR_ABORT;
4926 goto out;
4927 }
4928
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004929 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 newsrv->state |= SRV_CHECKED;
4931 }
4932
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004933 if (!defsrv) {
4934 if (newsrv->state & SRV_BACKUP)
4935 curproxy->srv_bck++;
4936 else
4937 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004938
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004939 newsrv->prev_state = newsrv->state;
4940 }
William Lallemanda73203e2012-03-12 12:48:57 +01004941 }
4942
4943 else if (strcmp(args[0], "unique-id-format") == 0) {
4944 if (!*(args[1])) {
4945 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004949 free(curproxy->uniqueid_format_string);
4950 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004951 }
William Lallemanda73203e2012-03-12 12:48:57 +01004952
4953 else if (strcmp(args[0], "unique-id-header") == 0) {
4954 if (!*(args[1])) {
4955 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
4959 free(curproxy->header_unique_id);
4960 curproxy->header_unique_id = strdup(args[1]);
4961 }
4962
William Lallemand723b73a2012-02-08 16:37:49 +01004963 else if (strcmp(args[0], "log-format") == 0) {
4964 if (!*(args[1])) {
4965 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004969
4970 if (curproxy->logformat_string != default_http_log_format &&
4971 curproxy->logformat_string != default_tcp_log_format &&
4972 curproxy->logformat_string != clf_http_log_format)
4973 free(curproxy->logformat_string);
4974 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 }
William Lallemand723b73a2012-02-08 16:37:49 +01004976
William Lallemand0f99e342011-10-12 17:50:54 +02004977 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4978 /* delete previous herited or defined syslog servers */
4979 struct logsrv *back;
4980
4981 if (*(args[1]) != 0) {
4982 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
4985 }
4986
William Lallemand723b73a2012-02-08 16:37:49 +01004987 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4988 LIST_DEL(&tmplogsrv->list);
4989 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004990 }
4991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004992 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004993 struct logsrv *logsrv;
4994
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004996 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004997 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004998 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004999 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005000 LIST_INIT(&node->list);
5001 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005005
5006 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007
William Lallemand0f99e342011-10-12 17:50:54 +02005008 logsrv->facility = get_log_facility(args[2]);
5009 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015
William Lallemand0f99e342011-10-12 17:50:54 +02005016 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005018 logsrv->level = get_log_level(args[3]);
5019 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
5025 }
5026
William Lallemand0f99e342011-10-12 17:50:54 +02005027 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005028 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005029 logsrv->minlvl = get_log_level(args[4]);
5030 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005031 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005035 }
5036 }
5037
Robert Tsai81ae1952007-12-05 10:47:29 +01005038 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01005039 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040 if (!sk) {
5041 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01005042 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
William Lallemand0f99e342011-10-12 17:50:54 +02005046 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01005047 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005048 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01005049 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01005050 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
William Lallemand0f99e342011-10-12 17:50:54 +02005054 logsrv->addr = *sk;
5055 if (!get_host_port(&logsrv->addr))
5056 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
William Lallemand0f99e342011-10-12 17:50:54 +02005058
5059 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
5061 else {
5062 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5063 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 }
5068 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005069 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005070 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071
Willy Tarreau977b8e42006-12-29 14:19:17 +01005072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005074
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5077 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005081
5082 /* we must first clear any optional default setting */
5083 curproxy->options &= ~PR_O_TPXY_MASK;
5084 free(curproxy->iface_name);
5085 curproxy->iface_name = NULL;
5086 curproxy->iface_len = 0;
5087
Willy Tarreaud5191e72010-02-09 20:50:45 +01005088 sk = str2sa(args[1]);
5089 if (!sk) {
5090 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
5094 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005096
5097 cur_arg = 2;
5098 while (*(args[cur_arg])) {
5099 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005100#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5101#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5103 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5104 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005107 }
5108#endif
5109 if (!*args[cur_arg + 1]) {
5110 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5111 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114 }
5115
5116 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005117 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 curproxy->options |= PR_O_TPXY_CLI;
5119 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005120 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005121 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005122 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5123 char *name, *end;
5124
5125 name = args[cur_arg+1] + 7;
5126 while (isspace(*name))
5127 name++;
5128
5129 end = name;
5130 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5131 end++;
5132
5133 curproxy->options &= ~PR_O_TPXY_MASK;
5134 curproxy->options |= PR_O_TPXY_DYN;
5135 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5136 curproxy->bind_hdr_len = end - name;
5137 memcpy(curproxy->bind_hdr_name, name, end - name);
5138 curproxy->bind_hdr_name[end-name] = '\0';
5139 curproxy->bind_hdr_occ = -1;
5140
5141 /* now look for an occurrence number */
5142 while (isspace(*end))
5143 end++;
5144 if (*end == ',') {
5145 end++;
5146 name = end;
5147 if (*end == '-')
5148 end++;
5149 while (isdigit(*end))
5150 end++;
5151 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5152 }
5153
5154 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5155 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5156 " occurrences values smaller than %d.\n",
5157 file, linenum, MAX_HDR_HISTORY);
5158 err_code |= ERR_ALERT | ERR_FATAL;
5159 goto out;
5160 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005161 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005162 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005163 if (!sk) {
5164 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
5167 }
5168 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005169 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005170 }
5171 global.last_checks |= LSTCHK_NETADM;
5172#if !defined(CONFIG_HAP_LINUX_TPROXY)
5173 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005174#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005175#else /* no TPROXY support */
5176 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005177 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005180#endif
5181 cur_arg += 2;
5182 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005183 }
5184
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005185 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5186#ifdef SO_BINDTODEVICE
5187 if (!*args[cur_arg + 1]) {
5188 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5189 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005192 }
5193 if (curproxy->iface_name)
5194 free(curproxy->iface_name);
5195
5196 curproxy->iface_name = strdup(args[cur_arg + 1]);
5197 curproxy->iface_len = strlen(curproxy->iface_name);
5198 global.last_checks |= LSTCHK_NETADM;
5199#else
5200 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5201 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005204#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005205 cur_arg += 2;
5206 continue;
5207 }
5208 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5209 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005214 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5215 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5216 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227
5228 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005229 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005230 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005231 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
5234 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005236 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005237 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
5241 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005243 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005244 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005245 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
5248 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005250 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005251 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
5255 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005257 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005258 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005262 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005265 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005268 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005269 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005271 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005272 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005274 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005275 }
5276 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005279 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290
5291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005293 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005299 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005300 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
5304 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005306 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005307 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 }
5311 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005313 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005314 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
5318 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005320 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005321 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005325 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005326 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005327 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005328 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005330 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005333 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005334
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 if (curproxy == &defproxy) {
5336 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005340 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005341 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 if (*(args[1]) == 0) {
5344 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005349 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005350 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5351 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5352 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5357 }
5358 else if (*args[2]) {
5359 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5360 file, linenum, args[0], args[2]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005365 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005366 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005367 wl->s = strdup(args[1]);
5368 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005369 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005378
Willy Tarreauade5ec42010-01-28 19:33:49 +01005379 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005380 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005381 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005382 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 }
5385 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005386 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005387 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005388 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005389 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 }
5392 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005393 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005394 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005395 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005396 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 }
5399 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005400 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 }
5406
Willy Tarreauade5ec42010-01-28 19:33:49 +01005407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005408 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005409 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
5413 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005415 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
5420 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005422 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005423 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005428 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005429
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 if (curproxy == &defproxy) {
5431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005435 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005436 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 if (*(args[1]) == 0) {
5439 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005444 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005445 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5446 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5447 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451 err_code |= warnif_cond_requires_req(cond, file, linenum);
5452 }
5453 else if (*args[2]) {
5454 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5455 file, linenum, args[0], args[2]);
5456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458 }
5459
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005460 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005461 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005462 wl->s = strdup(args[1]);
5463 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 }
5465 else if (!strcmp(args[0], "errorloc") ||
5466 !strcmp(args[0], "errorloc302") ||
5467 !strcmp(args[0], "errorloc303")) { /* error location */
5468 int errnum, errlen;
5469 char *err;
5470
Willy Tarreau977b8e42006-12-29 14:19:17 +01005471 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005472 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005473
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005475 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 }
5479
5480 errnum = atol(args[1]);
5481 if (!strcmp(args[0], "errorloc303")) {
5482 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5483 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5484 } else {
5485 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5486 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5487 }
5488
Willy Tarreau0f772532006-12-23 20:51:41 +01005489 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5490 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005491 chunk_destroy(&curproxy->errmsg[rc]);
5492 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005493 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005496
5497 if (rc >= HTTP_ERR_SIZE) {
5498 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5499 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 free(err);
5501 }
5502 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005503 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5504 int errnum, errlen, fd;
5505 char *err;
5506 struct stat stat;
5507
5508 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005509 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005510
5511 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005512 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005515 }
5516
5517 fd = open(args[2], O_RDONLY);
5518 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5519 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5520 file, linenum, args[2], args[1]);
5521 if (fd >= 0)
5522 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005525 }
5526
Willy Tarreau27a674e2009-08-17 07:23:33 +02005527 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005528 errlen = stat.st_size;
5529 } else {
5530 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005531 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005532 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005533 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005534 }
5535
5536 err = malloc(errlen); /* malloc() must succeed during parsing */
5537 errnum = read(fd, err, errlen);
5538 if (errnum != errlen) {
5539 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5540 file, linenum, args[2], args[1]);
5541 close(fd);
5542 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005545 }
5546 close(fd);
5547
5548 errnum = atol(args[1]);
5549 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5550 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005551 chunk_destroy(&curproxy->errmsg[rc]);
5552 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005553 break;
5554 }
5555 }
5556
5557 if (rc >= HTTP_ERR_SIZE) {
5558 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5559 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005561 free(err);
5562 }
5563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005565 struct cfg_kw_list *kwl;
5566 int index;
5567
5568 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5569 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5570 if (kwl->kw[index].section != CFG_LISTEN)
5571 continue;
5572 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5573 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005574 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005575 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005576 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005577 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005578 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005581 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005582 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005583 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_WARN;
5585 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005586 }
Willy Tarreau93893792009-07-23 13:19:11 +02005587 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005588 }
5589 }
5590 }
5591
Willy Tarreau6daf3432008-01-22 16:44:08 +01005592 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 }
Willy Tarreau93893792009-07-23 13:19:11 +02005596 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005597 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005598 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599}
5600
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005601int
5602cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5603{
5604
5605 int err_code = 0;
5606 const char *err;
5607
5608 if (!strcmp(args[0], "userlist")) { /* new userlist */
5609 struct userlist *newul;
5610
5611 if (!*args[1]) {
5612 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5613 file, linenum, args[0]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617
5618 err = invalid_char(args[1]);
5619 if (err) {
5620 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5621 file, linenum, *err, args[0], args[1]);
5622 err_code |= ERR_ALERT | ERR_FATAL;
5623 goto out;
5624 }
5625
5626 for (newul = userlist; newul; newul = newul->next)
5627 if (!strcmp(newul->name, args[1])) {
5628 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5629 file, linenum, args[1]);
5630 err_code |= ERR_WARN;
5631 goto out;
5632 }
5633
5634 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5635 if (!newul) {
5636 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5637 err_code |= ERR_ALERT | ERR_ABORT;
5638 goto out;
5639 }
5640
5641 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5642 newul->name = strdup(args[1]);
5643
5644 if (!newul->groupusers | !newul->name) {
5645 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5646 err_code |= ERR_ALERT | ERR_ABORT;
5647 goto out;
5648 }
5649
5650 newul->next = userlist;
5651 userlist = newul;
5652
5653 } else if (!strcmp(args[0], "group")) { /* new group */
5654 int cur_arg, i;
5655 const char *err;
5656
5657 if (!*args[1]) {
5658 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5659 file, linenum, args[0]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663
5664 err = invalid_char(args[1]);
5665 if (err) {
5666 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5667 file, linenum, *err, args[0], args[1]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671
5672 for(i = 0; i < userlist->grpcnt; i++)
5673 if (!strcmp(userlist->groups[i], args[1])) {
5674 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5675 file, linenum, args[1], userlist->name);
5676 err_code |= ERR_ALERT;
5677 goto out;
5678 }
5679
5680 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5681 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5682 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
5685 }
5686
5687 cur_arg = 2;
5688
5689 while (*args[cur_arg]) {
5690 if (!strcmp(args[cur_arg], "users")) {
5691 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5692 cur_arg += 2;
5693 continue;
5694 } else {
5695 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5696 file, linenum, args[0]);
5697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
5699 }
5700 }
5701
5702 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5703 } else if (!strcmp(args[0], "user")) { /* new user */
5704 struct auth_users *newuser;
5705 int cur_arg;
5706
5707 if (!*args[1]) {
5708 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5709 file, linenum, args[0]);
5710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
5712 }
5713
5714 for (newuser = userlist->users; newuser; newuser = newuser->next)
5715 if (!strcmp(newuser->user, args[1])) {
5716 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5717 file, linenum, args[1], userlist->name);
5718 err_code |= ERR_ALERT;
5719 goto out;
5720 }
5721
5722 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5723 if (!newuser) {
5724 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5725 err_code |= ERR_ALERT | ERR_ABORT;
5726 goto out;
5727 }
5728
5729 newuser->user = strdup(args[1]);
5730
5731 newuser->next = userlist->users;
5732 userlist->users = newuser;
5733
5734 cur_arg = 2;
5735
5736 while (*args[cur_arg]) {
5737 if (!strcmp(args[cur_arg], "password")) {
5738#ifndef CONFIG_HAP_CRYPT
5739 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5740 file, linenum);
5741 err_code |= ERR_ALERT;
5742#endif
5743 newuser->pass = strdup(args[cur_arg + 1]);
5744 cur_arg += 2;
5745 continue;
5746 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5747 newuser->pass = strdup(args[cur_arg + 1]);
5748 newuser->flags |= AU_O_INSECURE;
5749 cur_arg += 2;
5750 continue;
5751 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005752 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005753 cur_arg += 2;
5754 continue;
5755 } else {
5756 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5757 file, linenum, args[0]);
5758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
5761 }
5762 } else {
5763 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 }
5766
5767out:
5768 return err_code;
5769}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770
5771/*
5772 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005773 * Returns the error code, 0 if OK, or any combination of :
5774 * - ERR_ABORT: must abort ASAP
5775 * - ERR_FATAL: we can continue parsing but not start the service
5776 * - ERR_WARN: a warning has been emitted
5777 * - ERR_ALERT: an alert has been emitted
5778 * Only the two first ones can stop processing, the two others are just
5779 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005781int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005783 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 FILE *f;
5785 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005787 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 if ((f=fopen(file,"r")) == NULL)
5790 return -1;
5791
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005792 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005793 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005794 char *end;
5795 char *args[MAX_LINE_ARGS + 1];
5796 char *line = thisline;
5797
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 linenum++;
5799
5800 end = line + strlen(line);
5801
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005802 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5803 /* Check if we reached the limit and the last char is not \n.
5804 * Watch out for the last line without the terminating '\n'!
5805 */
5806 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005807 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005808 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005809 }
5810
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005812 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 line++;
5814
5815 arg = 0;
5816 args[arg] = line;
5817
5818 while (*line && arg < MAX_LINE_ARGS) {
5819 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5820 * C equivalent value. Other combinations left unchanged (eg: \1).
5821 */
5822 if (*line == '\\') {
5823 int skip = 0;
5824 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5825 *line = line[1];
5826 skip = 1;
5827 }
5828 else if (line[1] == 'r') {
5829 *line = '\r';
5830 skip = 1;
5831 }
5832 else if (line[1] == 'n') {
5833 *line = '\n';
5834 skip = 1;
5835 }
5836 else if (line[1] == 't') {
5837 *line = '\t';
5838 skip = 1;
5839 }
5840 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005841 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 unsigned char hex1, hex2;
5843 hex1 = toupper(line[2]) - '0';
5844 hex2 = toupper(line[3]) - '0';
5845 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5846 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5847 *line = (hex1<<4) + hex2;
5848 skip = 3;
5849 }
5850 else {
5851 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005852 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 }
5854 }
5855 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005856 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005857 end -= skip;
5858 }
5859 line++;
5860 }
5861 else if (*line == '#' || *line == '\n' || *line == '\r') {
5862 /* end of string, end of loop */
5863 *line = 0;
5864 break;
5865 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005866 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005868 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005869 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 line++;
5871 args[++arg] = line;
5872 }
5873 else {
5874 line++;
5875 }
5876 }
5877
5878 /* empty line */
5879 if (!**args)
5880 continue;
5881
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005882 if (*line) {
5883 /* we had to stop due to too many args.
5884 * Let's terminate the string, print the offending part then cut the
5885 * last arg.
5886 */
5887 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5888 line++;
5889 *line = '\0';
5890
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005891 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005892 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005893 err_code |= ERR_ALERT | ERR_FATAL;
5894 args[arg] = line;
5895 }
5896
Willy Tarreau540abe42007-05-02 20:50:16 +02005897 /* zero out remaining args and ensure that at least one entry
5898 * is zeroed out.
5899 */
5900 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 args[arg] = line;
5902 }
5903
Willy Tarreau3842f002009-06-14 11:39:52 +02005904 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005905 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005906 char *tmp;
5907
Willy Tarreau3842f002009-06-14 11:39:52 +02005908 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005909 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005910 for (arg=0; *args[arg+1]; arg++)
5911 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005912 *tmp = '\0'; // fix the next arg to \0
5913 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005914 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005915 else if (!strcmp(args[0], "default")) {
5916 kwm = KWM_DEF;
5917 for (arg=0; *args[arg+1]; arg++)
5918 args[arg] = args[arg+1]; // shift args after inversion
5919 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005920
William Lallemand0f99e342011-10-12 17:50:54 +02005921 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5922 strcmp(args[0], "log") != 0) {
5923 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005924 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005925 }
5926
Willy Tarreau977b8e42006-12-29 14:19:17 +01005927 if (!strcmp(args[0], "listen") ||
5928 !strcmp(args[0], "frontend") ||
5929 !strcmp(args[0], "backend") ||
5930 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005931 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005933 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005934 cursection = strdup(args[0]);
5935 }
5936 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005938 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005939 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005940 }
5941 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005942 confsect = CFG_USERLIST;
5943 free(cursection);
5944 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005945 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005946 else if (!strcmp(args[0], "peers")) {
5947 confsect = CFG_PEERS;
5948 free(cursection);
5949 cursection = strdup(args[0]);
5950 }
5951
Willy Tarreaubaaee002006-06-26 02:48:02 +02005952 /* else it's a section keyword */
5953
5954 switch (confsect) {
5955 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005956 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 break;
5958 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005959 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005961 case CFG_USERLIST:
5962 err_code |= cfg_parse_users(file, linenum, args, kwm);
5963 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005964 case CFG_PEERS:
5965 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5966 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005968 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005971
5972 if (err_code & ERR_ABORT)
5973 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005975 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005976 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005978 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979}
5980
Willy Tarreaubb925012009-07-23 13:36:36 +02005981/*
5982 * Returns the error code, 0 if OK, or any combination of :
5983 * - ERR_ABORT: must abort ASAP
5984 * - ERR_FATAL: we can continue parsing but not start the service
5985 * - ERR_WARN: a warning has been emitted
5986 * - ERR_ALERT: an alert has been emitted
5987 * Only the two first ones can stop processing, the two others are just
5988 * indicators.
5989 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005990int check_config_validity()
5991{
5992 int cfgerr = 0;
5993 struct proxy *curproxy = NULL;
5994 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005995 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005996 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005997 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005998 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005999
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006000 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 /*
6002 * Now, check for the integrity of all that we have collected.
6003 */
6004
6005 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006006 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006008 /* first, we will invert the proxy list order */
6009 curproxy = NULL;
6010 while (proxy) {
6011 struct proxy *next;
6012
6013 next = proxy->next;
6014 proxy->next = curproxy;
6015 curproxy = proxy;
6016 if (!next)
6017 break;
6018 proxy = next;
6019 }
6020
Willy Tarreaubaaee002006-06-26 02:48:02 +02006021 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006022 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006023 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006024 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006025 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006026 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006027 unsigned int next_id;
6028
6029 if (!curproxy->uuid) {
6030 /* proxy ID not set, use automatic numbering with first
6031 * spare entry starting with next_pxid.
6032 */
6033 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6034 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6035 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006036 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006037 next_pxid++;
6038
Willy Tarreau55ea7572007-06-17 19:56:27 +02006039
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006041 /* ensure we don't keep listeners uselessly bound */
6042 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 curproxy = curproxy->next;
6044 continue;
6045 }
6046
Willy Tarreauff01a212009-03-15 13:46:16 +01006047 switch (curproxy->mode) {
6048 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006049 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006050 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006051 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6052 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006053 cfgerr++;
6054 }
6055
6056 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006057 Warning("config : servers will be ignored for %s '%s'.\n",
6058 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006059 break;
6060
6061 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006062 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006063 break;
6064
6065 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006066 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006067 break;
6068 }
6069
6070 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006071 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
6072 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006073 cfgerr++;
6074 }
Willy Tarreauff01a212009-03-15 13:46:16 +01006075
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006076 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006077 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006078 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006079 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6080 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006081 cfgerr++;
6082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006084 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006085 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6086 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006087 cfgerr++;
6088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006090 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006091 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6092 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006093 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006094 }
6095 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006096 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006097 /* If no LB algo is set in a backend, and we're not in
6098 * transparent mode, dispatch mode nor proxy mode, we
6099 * want to use balance roundrobin by default.
6100 */
6101 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6102 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 }
6104 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006105
Willy Tarreau1620ec32011-08-06 17:05:02 +02006106 if (curproxy->options & PR_O_DISPATCH)
6107 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6108 else if (curproxy->options & PR_O_HTTP_PROXY)
6109 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6110 else if (curproxy->options & PR_O_TRANSP)
6111 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006112
Willy Tarreau1620ec32011-08-06 17:05:02 +02006113 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6114 if (curproxy->options & PR_O_DISABLE404) {
6115 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6116 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->options &= ~PR_O_DISABLE404;
6119 }
6120 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6121 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6122 "send-state", proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options &= ~PR_O2_CHK_SNDST;
6125 }
Willy Tarreauef781042010-01-27 11:53:01 +01006126 }
6127
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006128 /* if a default backend was specified, let's find it */
6129 if (curproxy->defbe.name) {
6130 struct proxy *target;
6131
Alex Williams96532db2009-11-01 21:27:13 -05006132 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006133 if (!target) {
6134 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6135 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006136 cfgerr++;
6137 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006138 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6139 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006140 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006141 } else {
6142 free(curproxy->defbe.name);
6143 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006144 /* we force the backend to be present on at least all of
6145 * the frontend's processes.
6146 */
6147 target->bind_proc = curproxy->bind_proc ?
6148 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006149
6150 /* Emit a warning if this proxy also has some servers */
6151 if (curproxy->srv) {
6152 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6153 curproxy->id);
6154 err_code |= ERR_WARN;
6155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
6157 }
6158
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006159 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006160 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6161 /* map jump target for ACT_SETBE in req_rep chain */
6162 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006163 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006164 struct proxy *target;
6165
Willy Tarreaua496b602006-12-17 23:15:24 +01006166 if (exp->action != ACT_SETBE)
6167 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006168
Alex Williams96532db2009-11-01 21:27:13 -05006169 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006170 if (!target) {
6171 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6172 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006173 cfgerr++;
6174 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006175 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6176 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006177 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006178 } else {
6179 free((void *)exp->replace);
6180 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006181 /* we force the backend to be present on at least all of
6182 * the frontend's processes.
6183 */
6184 target->bind_proc = curproxy->bind_proc ?
6185 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006186 }
6187 }
6188 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006189
6190 /* find the target proxy for 'use_backend' rules */
6191 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006192 struct proxy *target;
6193
Alex Williams96532db2009-11-01 21:27:13 -05006194 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006195
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006196 if (!target) {
6197 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6198 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006199 cfgerr++;
6200 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006201 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6202 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006203 cfgerr++;
6204 } else {
6205 free((void *)rule->be.name);
6206 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006207 /* we force the backend to be present on at least all of
6208 * the frontend's processes.
6209 */
6210 target->bind_proc = curproxy->bind_proc ?
6211 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006212 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006213 }
6214
6215 /* find the target proxy for 'use_backend' rules */
6216 list_for_each_entry(srule, &curproxy->server_rules, list) {
6217 struct server *target = findserver(curproxy, srule->srv.name);
6218
6219 if (!target) {
6220 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6221 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6222 cfgerr++;
6223 continue;
6224 }
6225 free((void *)srule->srv.name);
6226 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006227 }
6228
Emeric Brunb982a3d2010-01-04 15:45:53 +01006229 /* find the target table for 'stick' rules */
6230 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6231 struct proxy *target;
6232
Emeric Brun1d33b292010-01-04 15:47:17 +01006233 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6234 if (mrule->flags & STK_IS_STORE)
6235 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6236
Emeric Brunb982a3d2010-01-04 15:45:53 +01006237 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006238 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006239 else
6240 target = curproxy;
6241
6242 if (!target) {
6243 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6244 curproxy->id, mrule->table.name);
6245 cfgerr++;
6246 }
6247 else if (target->table.size == 0) {
6248 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6249 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6250 cfgerr++;
6251 }
Willy Tarreau12785782012-04-27 21:37:17 +02006252 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6253 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006254 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6255 cfgerr++;
6256 }
6257 else {
6258 free((void *)mrule->table.name);
6259 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006260 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006261 }
6262 }
6263
6264 /* find the target table for 'store response' rules */
6265 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6266 struct proxy *target;
6267
Emeric Brun1d33b292010-01-04 15:47:17 +01006268 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6269
Emeric Brunb982a3d2010-01-04 15:45:53 +01006270 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006271 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006272 else
6273 target = curproxy;
6274
6275 if (!target) {
6276 Alert("Proxy '%s': unable to find store table '%s'.\n",
6277 curproxy->id, mrule->table.name);
6278 cfgerr++;
6279 }
6280 else if (target->table.size == 0) {
6281 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6282 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6283 cfgerr++;
6284 }
Willy Tarreau12785782012-04-27 21:37:17 +02006285 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6286 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006287 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6288 cfgerr++;
6289 }
6290 else {
6291 free((void *)mrule->table.name);
6292 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006293 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006294 }
6295 }
6296
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006297 /* find the target table for 'tcp-request' layer 4 rules */
6298 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6299 struct proxy *target;
6300
Willy Tarreau56123282010-08-06 19:06:56 +02006301 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006302 continue;
6303
6304 if (trule->act_prm.trk_ctr.table.n)
6305 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6306 else
6307 target = curproxy;
6308
6309 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006310 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6311 curproxy->id, trule->act_prm.trk_ctr.table.n,
6312 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006313 cfgerr++;
6314 }
6315 else if (target->table.size == 0) {
6316 Alert("Proxy '%s': table '%s' used but not configured.\n",
6317 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6318 cfgerr++;
6319 }
6320 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006321 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006322 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6323 cfgerr++;
6324 }
6325 else {
6326 free(trule->act_prm.trk_ctr.table.n);
6327 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006328 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006329 * to pass a list of counters to track and allocate them right here using
6330 * stktable_alloc_data_type().
6331 */
6332 }
6333 }
6334
Willy Tarreaud1f96522010-08-03 19:34:32 +02006335 /* find the target table for 'tcp-request' layer 6 rules */
6336 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6337 struct proxy *target;
6338
Willy Tarreau56123282010-08-06 19:06:56 +02006339 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006340 continue;
6341
6342 if (trule->act_prm.trk_ctr.table.n)
6343 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6344 else
6345 target = curproxy;
6346
6347 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006348 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6349 curproxy->id, trule->act_prm.trk_ctr.table.n,
6350 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006351 cfgerr++;
6352 }
6353 else if (target->table.size == 0) {
6354 Alert("Proxy '%s': table '%s' used but not configured.\n",
6355 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6356 cfgerr++;
6357 }
6358 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006359 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 +02006360 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6361 cfgerr++;
6362 }
6363 else {
6364 free(trule->act_prm.trk_ctr.table.n);
6365 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006366 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006367 * to pass a list of counters to track and allocate them right here using
6368 * stktable_alloc_data_type().
6369 */
6370 }
6371 }
6372
Emeric Brun32da3c42010-09-23 18:39:19 +02006373 if (curproxy->table.peers.name) {
6374 struct peers *curpeers = peers;
6375
6376 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6377 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6378 free((void *)curproxy->table.peers.name);
6379 curproxy->table.peers.p = peers;
6380 break;
6381 }
6382 }
6383
6384 if (!curpeers) {
6385 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6386 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006387 free((void *)curproxy->table.peers.name);
6388 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006389 cfgerr++;
6390 }
6391 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006392 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6393 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006394 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006395 cfgerr++;
6396 }
6397 }
6398
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006399 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006400 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006401 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6402 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6403 "proxy", curproxy->id);
6404 cfgerr++;
6405 goto out_uri_auth_compat;
6406 }
6407
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006408 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006409 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006410 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006411 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006412
Willy Tarreau95fa4692010-02-01 13:05:50 +01006413 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6414 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006415
6416 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006417 uri_auth_compat_req[i++] = "realm";
6418 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6419 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006420
Willy Tarreau95fa4692010-02-01 13:05:50 +01006421 uri_auth_compat_req[i++] = "unless";
6422 uri_auth_compat_req[i++] = "{";
6423 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6424 uri_auth_compat_req[i++] = "}";
6425 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006426
Willy Tarreauff011f22011-01-06 17:51:27 +01006427 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6428 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006429 cfgerr++;
6430 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006431 }
6432
Willy Tarreauff011f22011-01-06 17:51:27 +01006433 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006434
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006435 if (curproxy->uri_auth->auth_realm) {
6436 free(curproxy->uri_auth->auth_realm);
6437 curproxy->uri_auth->auth_realm = NULL;
6438 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006439
6440 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006441 }
6442out_uri_auth_compat:
6443
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006444 cfgerr += acl_find_targets(curproxy);
6445
Willy Tarreau2738a142006-07-08 17:28:09 +02006446 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006447 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006448 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006449 (!curproxy->timeout.connect ||
6450 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006451 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006452 " | While not properly invalid, you will certainly encounter various problems\n"
6453 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006454 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006455 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006456 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006457 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006458
Willy Tarreau1fa31262007-12-03 00:36:16 +01006459 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6460 * We must still support older configurations, so let's find out whether those
6461 * parameters have been set or must be copied from contimeouts.
6462 */
6463 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006464 if (!curproxy->timeout.tarpit ||
6465 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006466 /* tarpit timeout not set. We search in the following order:
6467 * default.tarpit, curr.connect, default.connect.
6468 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006469 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006470 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006471 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006472 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006473 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006474 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006475 }
6476 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006477 (!curproxy->timeout.queue ||
6478 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006479 /* queue timeout not set. We search in the following order:
6480 * default.queue, curr.connect, default.connect.
6481 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006482 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006483 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006484 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006485 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006486 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006487 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006488 }
6489 }
6490
Willy Tarreau1620ec32011-08-06 17:05:02 +02006491 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006492 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6493 curproxy->check_req = (char *)malloc(curproxy->check_len);
6494 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006495 }
6496
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006497 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006498 if (curproxy->nb_req_cap) {
6499 if (curproxy->mode == PR_MODE_HTTP) {
6500 curproxy->req_cap_pool = create_pool("ptrcap",
6501 curproxy->nb_req_cap * sizeof(char *),
6502 MEM_F_SHARED);
6503 } else {
6504 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6505 proxy_type_str(curproxy), curproxy->id);
6506 err_code |= ERR_WARN;
6507 curproxy->to_log &= ~LW_REQHDR;
6508 curproxy->nb_req_cap = 0;
6509 }
6510 }
6511
6512 if (curproxy->nb_rsp_cap) {
6513 if (curproxy->mode == PR_MODE_HTTP) {
6514 curproxy->rsp_cap_pool = create_pool("ptrcap",
6515 curproxy->nb_rsp_cap * sizeof(char *),
6516 MEM_F_SHARED);
6517 } else {
6518 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6519 proxy_type_str(curproxy), curproxy->id);
6520 err_code |= ERR_WARN;
6521 curproxy->to_log &= ~LW_REQHDR;
6522 curproxy->nb_rsp_cap = 0;
6523 }
6524 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006525
Willy Tarreau196729e2012-05-31 19:30:26 +02006526 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006527 if (!(curproxy->cap & PR_CAP_FE)) {
6528 if (curproxy->logformat_string != default_http_log_format &&
6529 curproxy->logformat_string != default_tcp_log_format &&
6530 curproxy->logformat_string != clf_http_log_format)
6531 free(curproxy->logformat_string);
6532 curproxy->logformat_string = NULL;
6533 }
6534
Willy Tarreau196729e2012-05-31 19:30:26 +02006535 if (curproxy->logformat_string)
6536 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6537
6538 if (curproxy->uniqueid_format_string)
6539 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6540
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 /* first, we will invert the servers list order */
6542 newsrv = NULL;
6543 while (curproxy->srv) {
6544 struct server *next;
6545
6546 next = curproxy->srv->next;
6547 curproxy->srv->next = newsrv;
6548 newsrv = curproxy->srv;
6549 if (!next)
6550 break;
6551 curproxy->srv = next;
6552 }
6553
Willy Tarreaudd701652010-05-25 23:03:02 +02006554 /* assign automatic UIDs to servers which don't have one yet */
6555 next_id = 1;
6556 newsrv = curproxy->srv;
6557 while (newsrv != NULL) {
6558 if (!newsrv->puid) {
6559 /* server ID not set, use automatic numbering with first
6560 * spare entry starting with next_svid.
6561 */
6562 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6563 newsrv->conf.id.key = newsrv->puid = next_id;
6564 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6565 }
6566 next_id++;
6567 newsrv = newsrv->next;
6568 }
6569
Willy Tarreau20697042007-11-15 23:26:18 +01006570 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006571 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572
Willy Tarreau62c3be22012-01-20 13:12:32 +01006573 /*
6574 * If this server supports a maxconn parameter, it needs a dedicated
6575 * tasks to fill the emptied slots when a connection leaves.
6576 * Also, resolve deferred tracking dependency if needed.
6577 */
6578 newsrv = curproxy->srv;
6579 while (newsrv != NULL) {
6580 if (newsrv->minconn > newsrv->maxconn) {
6581 /* Only 'minconn' was specified, or it was higher than or equal
6582 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6583 * this will avoid further useless expensive computations.
6584 */
6585 newsrv->maxconn = newsrv->minconn;
6586 } else if (newsrv->maxconn && !newsrv->minconn) {
6587 /* minconn was not specified, so we set it to maxconn */
6588 newsrv->minconn = newsrv->maxconn;
6589 }
6590
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006591#ifdef USE_OPENSSL
6592#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6593#define SSL_OP_NO_COMPRESSION 0
6594#endif
6595#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6596#define SSL_MODE_RELEASE_BUFFERS 0
6597#endif
6598#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6599#define SSL_OP_NO_COMPRESSION 0
6600#endif
6601 if (newsrv->use_ssl) {
6602 int ssloptions =
6603 SSL_OP_ALL | /* all known workarounds for bugs */
6604 SSL_OP_NO_SSLv2 |
6605 SSL_OP_NO_COMPRESSION;
6606 int sslmode =
6607 SSL_MODE_ENABLE_PARTIAL_WRITE |
6608 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6609 SSL_MODE_RELEASE_BUFFERS;
6610
6611 /* Initiate SSL context for current server */
6612 newsrv->ssl_ctx.reused_sess = NULL;
6613 newsrv->data = &ssl_sock;
6614 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6615 if(!newsrv->ssl_ctx.ctx) {
6616
6617 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6618 proxy_type_str(curproxy), curproxy->id,
6619 newsrv->id);
6620 cfgerr++;
6621 goto next_srv;
6622 }
6623
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006624 if (newsrv->ssl_ctx.nosslv3)
6625 ssloptions |= SSL_OP_NO_SSLv3;
6626 if (newsrv->ssl_ctx.notlsv1)
6627 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006628 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6629 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6630 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6631 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006632 if (newsrv->ssl_ctx.ciphers &&
6633 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6634 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6635 curproxy->id, newsrv->id,
6636 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6637 cfgerr++;
6638 goto next_srv;
6639 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006640 }
6641#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006642 if (newsrv->trackit) {
6643 struct proxy *px;
6644 struct server *srv;
6645 char *pname, *sname;
6646
6647 pname = newsrv->trackit;
6648 sname = strrchr(pname, '/');
6649
6650 if (sname)
6651 *sname++ = '\0';
6652 else {
6653 sname = pname;
6654 pname = NULL;
6655 }
6656
6657 if (pname) {
6658 px = findproxy(pname, PR_CAP_BE);
6659 if (!px) {
6660 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6661 proxy_type_str(curproxy), curproxy->id,
6662 newsrv->id, pname);
6663 cfgerr++;
6664 goto next_srv;
6665 }
6666 } else
6667 px = curproxy;
6668
6669 srv = findserver(px, sname);
6670 if (!srv) {
6671 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6672 proxy_type_str(curproxy), curproxy->id,
6673 newsrv->id, sname);
6674 cfgerr++;
6675 goto next_srv;
6676 }
6677
6678 if (!(srv->state & SRV_CHECKED)) {
6679 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6680 "tracking as it does not have checks enabled.\n",
6681 proxy_type_str(curproxy), curproxy->id,
6682 newsrv->id, px->id, srv->id);
6683 cfgerr++;
6684 goto next_srv;
6685 }
6686
6687 if (curproxy != px &&
6688 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6689 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6690 "tracking: disable-on-404 option inconsistency.\n",
6691 proxy_type_str(curproxy), curproxy->id,
6692 newsrv->id, px->id, srv->id);
6693 cfgerr++;
6694 goto next_srv;
6695 }
6696
6697 /* if the other server is forced disabled, we have to do the same here */
6698 if (srv->state & SRV_MAINTAIN) {
6699 newsrv->state |= SRV_MAINTAIN;
6700 newsrv->state &= ~SRV_RUNNING;
6701 newsrv->health = 0;
6702 }
6703
6704 newsrv->track = srv;
6705 newsrv->tracknext = srv->tracknext;
6706 srv->tracknext = newsrv;
6707
6708 free(newsrv->trackit);
6709 newsrv->trackit = NULL;
6710 }
6711 next_srv:
6712 newsrv = newsrv->next;
6713 }
6714
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006715 /* We have to initialize the server lookup mechanism depending
6716 * on what LB algorithm was choosen.
6717 */
6718
6719 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6720 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6721 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006722 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6723 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6724 init_server_map(curproxy);
6725 } else {
6726 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6727 fwrr_init_server_groups(curproxy);
6728 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006729 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006730
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006731 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006732 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6733 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6734 fwlc_init_server_tree(curproxy);
6735 } else {
6736 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6737 fas_init_server_tree(curproxy);
6738 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006739 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006740
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006741 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006742 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6743 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6744 chash_init_server_tree(curproxy);
6745 } else {
6746 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6747 init_server_map(curproxy);
6748 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006749 break;
6750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006751
6752 if (curproxy->options & PR_O_LOGASAP)
6753 curproxy->to_log &= ~LW_BYTES;
6754
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006755 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006756 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006757 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6758 proxy_type_str(curproxy), curproxy->id);
6759 err_code |= ERR_WARN;
6760 }
6761
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006762 if (curproxy->mode != PR_MODE_HTTP) {
6763 int optnum;
6764
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006765 if (curproxy->uri_auth) {
6766 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6767 proxy_type_str(curproxy), curproxy->id);
6768 err_code |= ERR_WARN;
6769 curproxy->uri_auth = NULL;
6770 }
6771
Willy Tarreau87cf5142011-08-19 22:57:24 +02006772 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006773 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6774 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6775 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006776 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006777 }
6778
6779 if (curproxy->options & PR_O_ORGTO) {
6780 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6781 "originalto", proxy_type_str(curproxy), curproxy->id);
6782 err_code |= ERR_WARN;
6783 curproxy->options &= ~PR_O_ORGTO;
6784 }
6785
6786 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6787 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6788 (curproxy->cap & cfg_opts[optnum].cap) &&
6789 (curproxy->options & cfg_opts[optnum].val)) {
6790 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6791 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6792 err_code |= ERR_WARN;
6793 curproxy->options &= ~cfg_opts[optnum].val;
6794 }
6795 }
6796
6797 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6798 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6799 (curproxy->cap & cfg_opts2[optnum].cap) &&
6800 (curproxy->options2 & cfg_opts2[optnum].val)) {
6801 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6802 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6803 err_code |= ERR_WARN;
6804 curproxy->options2 &= ~cfg_opts2[optnum].val;
6805 }
6806 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006807
Willy Tarreauefa5f512010-03-30 20:13:29 +02006808#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006809 if (curproxy->bind_hdr_occ) {
6810 curproxy->bind_hdr_occ = 0;
6811 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6812 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6813 err_code |= ERR_WARN;
6814 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006815#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006816 }
6817
Willy Tarreaubaaee002006-06-26 02:48:02 +02006818 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006819 * ensure that we're not cross-dressing a TCP server into HTTP.
6820 */
6821 newsrv = curproxy->srv;
6822 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006823 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006824 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6825 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006826 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006827 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006828
Willy Tarreau0cec3312011-10-31 13:49:26 +01006829 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6830 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6831 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6832 err_code |= ERR_WARN;
6833 }
6834
Willy Tarreauefa5f512010-03-30 20:13:29 +02006835#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006836 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6837 newsrv->bind_hdr_occ = 0;
6838 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6839 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6840 err_code |= ERR_WARN;
6841 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006842#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006843 newsrv = newsrv->next;
6844 }
6845
Willy Tarreauc1a21672009-08-16 22:37:44 +02006846 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006847 curproxy->accept = frontend_accept;
6848
Willy Tarreauc1a21672009-08-16 22:37:44 +02006849 if (curproxy->tcp_req.inspect_delay ||
6850 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006851 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006852
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006853 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006854 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006855 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006856 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006857
6858 /* both TCP and HTTP must check switching rules */
6859 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6860 }
6861
6862 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006863 if (curproxy->tcp_req.inspect_delay ||
6864 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6865 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6866
Emeric Brun97679e72010-09-23 17:56:44 +02006867 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6868 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6869
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006870 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006871 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006872 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006873 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006874
6875 /* If the backend does requires RDP cookie persistence, we have to
6876 * enable the corresponding analyser.
6877 */
6878 if (curproxy->options2 & PR_O2_RDPC_PRST)
6879 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6880 }
6881
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006882 listener = NULL;
6883 while (curproxy->listen) {
6884 struct listener *next;
6885
6886 next = curproxy->listen->next;
6887 curproxy->listen->next = listener;
6888 listener = curproxy->listen;
6889
6890 if (!next)
6891 break;
6892
6893 curproxy->listen = next;
6894 }
6895
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006896 /* Configure SSL for each bind line.
6897 * Note: if configuration fails at some point, the ->ctx member
6898 * remains NULL so that listeners can later detach.
6899 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006900 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6901 if (!bind_conf->is_ssl)
6902 continue;
6903#ifdef USE_OPENSSL
6904 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006905 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006906 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006907 cfgerr++;
6908 continue;
6909 }
6910
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006911 if (shared_context_init(global.tune.sslcachesize) < 0) {
6912 Alert("Unable to allocate SSL session cache.\n");
6913 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006914 continue;
6915 }
6916
Emeric Brunfc0421f2012-09-07 17:30:07 +02006917 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006918 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006919#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006920 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006921
Willy Tarreaue6b98942007-10-29 01:09:36 +01006922 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006923 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006924 listener = curproxy->listen;
6925 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006926 if (!listener->luid) {
6927 /* listener ID not set, use automatic numbering with first
6928 * spare entry starting with next_luid.
6929 */
6930 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6931 listener->conf.id.key = listener->luid = next_id;
6932 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006933 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006934 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006935
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006936 /* enable separate counters */
6937 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6938 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6939 if (!listener->name) {
6940 sprintf(trash, "sock-%d", listener->luid);
6941 listener->name = strdup(trash);
6942 }
6943 }
Emeric Brun6e159292012-05-18 16:32:13 +02006944#ifdef USE_OPENSSL
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006945 if (listener->bind_conf->is_ssl && listener->bind_conf->default_ctx)
6946 listener->data = &ssl_sock; /* SSL data layer */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006947#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +01006948 if (curproxy->options & PR_O_TCP_NOLING)
6949 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006950 if (!listener->maxconn)
6951 listener->maxconn = curproxy->maxconn;
6952 if (!listener->backlog)
6953 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006954 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006955 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006956 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006957 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006958 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006959
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006960 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6961 listener->options |= LI_O_TCP_RULES;
6962
Willy Tarreaude3041d2010-05-31 10:56:17 +02006963 if (curproxy->mon_mask.s_addr)
6964 listener->options |= LI_O_CHK_MONNET;
6965
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006966 /* smart accept mode is automatic in HTTP mode */
6967 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006968 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006969 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6970 listener->options |= LI_O_NOQUICKACK;
6971
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006972 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006973 listener = listener->next;
6974 }
6975
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006976 /* Release unused SSL configs */
6977 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6978 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006979 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006980#ifdef USE_OPENSSL
6981 ssl_sock_free_all_ctx(bind_conf);
6982 free(bind_conf->ciphers);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006983#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006984 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006985
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006986 /* Check multi-process mode compatibility for the current proxy */
6987 if (global.nbproc > 1) {
6988 int nbproc = 0;
6989 if (curproxy->bind_proc) {
6990 int proc;
6991 for (proc = 0; proc < global.nbproc; proc++) {
6992 if (curproxy->bind_proc & (1 << proc)) {
6993 nbproc++;
6994 }
6995 }
6996 } else {
6997 nbproc = global.nbproc;
6998 }
6999 if (curproxy->table.peers.name) {
7000 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7001 curproxy->id);
7002 cfgerr++;
7003 }
7004 if (nbproc > 1) {
7005 if (curproxy->uri_auth) {
7006 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7007 curproxy->id);
7008 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7009 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7010 curproxy->id);
7011 }
7012 }
7013 if (curproxy->appsession_name) {
7014 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7015 curproxy->id);
7016 }
7017 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7018 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7019 curproxy->id);
7020 }
7021 }
7022 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007023
7024 /* create the task associated with the proxy */
7025 curproxy->task = task_new();
7026 if (curproxy->task) {
7027 curproxy->task->context = curproxy;
7028 curproxy->task->process = manage_proxy;
7029 /* no need to queue, it will be done automatically if some
7030 * listener gets limited.
7031 */
7032 curproxy->task->expire = TICK_ETERNITY;
7033 } else {
7034 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7035 curproxy->id);
7036 cfgerr++;
7037 }
7038
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 curproxy = curproxy->next;
7040 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007041
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007042 /* Check multi-process mode compatibility */
7043 if (global.nbproc > 1) {
7044 if (global.stats_fe) {
7045 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
7046 }
7047 }
7048
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007049 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7050 struct auth_users *curuser;
7051 int g;
7052
7053 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7054 unsigned int group_mask = 0;
7055 char *group = NULL;
7056
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007057 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007058 continue;
7059
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007060 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007061
7062 for (g = 0; g < curuserlist->grpcnt; g++)
7063 if (!strcmp(curuserlist->groups[g], group))
7064 break;
7065
7066 if (g == curuserlist->grpcnt) {
7067 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7068 curuserlist->name, group, curuser->user);
7069 err_code |= ERR_ALERT | ERR_FATAL;
7070 goto out;
7071 }
7072
7073 group_mask |= (1 << g);
7074 }
7075
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007076 free(curuser->u.groups);
7077 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007078 }
7079
7080 for (g = 0; g < curuserlist->grpcnt; g++) {
7081 char *user = NULL;
7082
7083 if (!curuserlist->groupusers[g])
7084 continue;
7085
7086 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7087 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7088 if (!strcmp(curuser->user, user))
7089 break;
7090
7091 if (!curuser) {
7092 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7093 curuserlist->name, user, curuserlist->groups[g]);
7094 err_code |= ERR_ALERT | ERR_FATAL;
7095 goto out;
7096 }
7097
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007098 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007099 }
7100
7101 free(curuserlist->groupusers[g]);
7102 }
7103
7104 free(curuserlist->groupusers);
7105
7106#ifdef DEBUG_AUTH
7107 for (g = 0; g < curuserlist->grpcnt; g++) {
7108 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7109
7110 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007111 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007112 fprintf(stderr, " %s", curuser->user);
7113 }
7114
7115 fprintf(stderr, "\n");
7116 }
7117#endif
7118
Willy Tarreaufbb78422011-06-05 15:38:35 +02007119 }
7120
7121 /* automatically compute fullconn if not set. We must not do it in the
7122 * loop above because cross-references are not yet fully resolved.
7123 */
7124 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7125 /* If <fullconn> is not set, let's set it to 10% of the sum of
7126 * the possible incoming frontend's maxconns.
7127 */
7128 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7129 struct proxy *fe;
7130 int total = 0;
7131
7132 /* sum up the number of maxconns of frontends which
7133 * reference this backend at least once or which are
7134 * the same one ('listen').
7135 */
7136 for (fe = proxy; fe; fe = fe->next) {
7137 struct switching_rule *rule;
7138 struct hdr_exp *exp;
7139 int found = 0;
7140
7141 if (!(fe->cap & PR_CAP_FE))
7142 continue;
7143
7144 if (fe == curproxy) /* we're on a "listen" instance */
7145 found = 1;
7146
7147 if (fe->defbe.be == curproxy) /* "default_backend" */
7148 found = 1;
7149
7150 /* check if a "use_backend" rule matches */
7151 if (!found) {
7152 list_for_each_entry(rule, &fe->switching_rules, list) {
7153 if (rule->be.backend == curproxy) {
7154 found = 1;
7155 break;
7156 }
7157 }
7158 }
7159
7160 /* check if a "reqsetbe" rule matches */
7161 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7162 if (exp->action == ACT_SETBE &&
7163 (struct proxy *)exp->replace == curproxy) {
7164 found = 1;
7165 break;
7166 }
7167 }
7168
7169 /* now we've checked all possible ways to reference a backend
7170 * from a frontend.
7171 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007172 if (!found)
7173 continue;
7174 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007175 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007176 /* we have the sum of the maxconns in <total>. We only
7177 * keep 10% of that sum to set the default fullconn, with
7178 * a hard minimum of 1 (to avoid a divide by zero).
7179 */
7180 curproxy->fullconn = (total + 9) / 10;
7181 if (!curproxy->fullconn)
7182 curproxy->fullconn = 1;
7183 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007184 }
7185
Willy Tarreau056f5682010-06-06 15:51:11 +02007186 /* initialize stick-tables on backend capable proxies. This must not
7187 * be done earlier because the data size may be discovered while parsing
7188 * other proxies.
7189 */
7190 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007191 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007192
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007193 /*
7194 * Recount currently required checks.
7195 */
7196
7197 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7198 int optnum;
7199
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007200 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7201 if (curproxy->options & cfg_opts[optnum].val)
7202 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007203
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007204 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7205 if (curproxy->options2 & cfg_opts2[optnum].val)
7206 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007207 }
7208
Willy Tarreau122541c2011-09-07 21:24:49 +02007209 if (peers) {
7210 struct peers *curpeers = peers, **last;
7211 struct peer *p, *pb;
7212
7213 /* Remove all peers sections which don't have a valid listener.
7214 * This can happen when a peers section is never referenced and
7215 * does not contain a local peer.
7216 */
7217 last = &peers;
7218 while (*last) {
7219 curpeers = *last;
7220 if (curpeers->peers_fe) {
7221 last = &curpeers->next;
7222 continue;
7223 }
7224
7225 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7226 curpeers->id, localpeer);
7227
7228 p = curpeers->remote;
7229 while (p) {
7230 pb = p->next;
7231 free(p->id);
7232 free(p);
7233 p = pb;
7234 }
7235
7236 /* Destroy and unlink this curpeers section.
7237 * Note: curpeers is backed up into *last.
7238 */
7239 free(curpeers->id);
7240 curpeers = curpeers->next;
7241 free(*last);
7242 *last = curpeers;
7243 }
7244 }
7245
Willy Tarreauac1932d2011-10-24 19:14:41 +02007246 if (!global.tune.max_http_hdr)
7247 global.tune.max_http_hdr = MAX_HTTP_HDR;
7248
Willy Tarreau34eb6712011-10-24 18:15:04 +02007249 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007250 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007251 MEM_F_SHARED);
7252
Willy Tarreaubb925012009-07-23 13:36:36 +02007253 if (cfgerr > 0)
7254 err_code |= ERR_ALERT | ERR_FATAL;
7255 out:
7256 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257}
7258
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007259/*
7260 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7261 * parsing sessions.
7262 */
7263void cfg_register_keywords(struct cfg_kw_list *kwl)
7264{
7265 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7266}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007267
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007268/*
7269 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7270 */
7271void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7272{
7273 LIST_DEL(&kwl->list);
7274 LIST_INIT(&kwl->list);
7275}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007276
7277/*
7278 * Local variables:
7279 * c-indent-level: 8
7280 * c-basic-offset: 8
7281 * End:
7282 */