blob: a45acb15d13d96c3dcb5b8014712c325238d6345 [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>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaud02394b2012-05-11 18:32:18 +020064#include <proto/sock_raw.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
68
Willy Tarreauf3c69202006-07-09 16:42:34 +020069/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
70 * ssl-hello-chk option to ensure that the remote server speaks SSL.
71 *
72 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
73 */
74const char sslv3_client_hello_pkt[] = {
75 "\x16" /* ContentType : 0x16 = Hanshake */
76 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
77 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
78 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
79 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
80 "\x03\x00" /* Hello Version : 0x0300 = v3 */
81 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
82 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
83 "\x00" /* Session ID length : empty (no session ID) */
84 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
85 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
86 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
87 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
88 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
89 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
90 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
91 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
92 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
93 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
94 "\x00\x38" "\x00\x39" "\x00\x3A"
95 "\x01" /* Compression Length : 0x01 = 1 byte for types */
96 "\x00" /* Compression Type : 0x00 = NULL compression */
97};
98
Willy Tarreau3842f002009-06-14 11:39:52 +020099/* various keyword modifiers */
100enum kw_mod {
101 KWM_STD = 0, /* normal */
102 KWM_NO, /* "no" prefixed before the keyword */
103 KWM_DEF, /* "default" prefixed before the keyword */
104};
105
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100107struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100108 const char *name;
109 unsigned int val;
110 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100112 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100113};
114
115/* proxy->options */
116static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100117{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100118 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
119 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
120 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
122 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
123 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
124 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
128 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
130 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
131 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
132 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
133 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100134#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100135 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100136#else
137 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100138#endif
139
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141};
142
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143/* proxy->options2 */
144static const struct cfg_opt cfg_opts2[] =
145{
146#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
149 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100150#else
151 { "splice-request", 0, 0, 0, 0 },
152 { "splice-response", 0, 0, 0, 0 },
153 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100154#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
156 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
158 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
159 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
160 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
162 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
163 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200165 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200166 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100167 { NULL, 0, 0, 0 }
168};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169
Willy Tarreau6daf3432008-01-22 16:44:08 +0100170static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
172int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100173int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200175/* List head of all known configuration keywords */
176static struct cfg_kw_list cfg_keywords = {
177 .list = LIST_HEAD_INIT(cfg_keywords.list)
178};
179
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180/*
181 * converts <str> to a list of listeners which are dynamically allocated.
182 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
183 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
184 * - <port> is a numerical port from 1 to 65535 ;
185 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
186 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200187 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190{
191 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100192 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200193 int port, end;
194
195 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197 while (next && *next) {
198 struct sockaddr_storage ss;
199
200 str = next;
201 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100202 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 *next++ = 0;
204 }
205
Emeric Bruned760922010-10-22 17:59:25 +0200206 if (*str == '/') {
207 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
208 /* so compute max path */
209 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
210 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 +0200211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100213 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
214 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200215 goto fail;
216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200219 ss.ss_family = AF_UNIX;
220 if (global.unix_bind.prefix) {
221 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
222 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 }
Emeric Bruned760922010-10-22 17:59:25 +0200224 else {
225 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
226 }
227 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 }
229 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100232 ss2 = str2sa_range(str, &port, &end);
233 if (!ss2) {
234 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
235 file, line, str);
236 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 if (!port) {
240 Alert("parsing [%s:%d] : missing port number: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 /* OK the address looks correct */
246 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Emeric Bruned760922010-10-22 17:59:25 +0200248 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
250 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200251 goto fail;
252 }
253
254 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259 }
260
261 for (; port <= end; port++) {
262 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200263 l->next = curproxy->listen;
264 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265
266 l->fd = -1;
267 l->addr = ss;
Emeric Brund88fd822012-05-18 18:30:29 +0200268 l->sock = &sock_raw;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 l->state = LI_INIT;
270
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100271 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100273 tcpv4_add_listener(l);
274 }
Emeric Bruned760922010-10-22 17:59:25 +0200275 else if (ss.ss_family == AF_INET6) {
276 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
277 tcpv6_add_listener(l);
278 }
279 else {
280 l->perm.ux.gid = l->perm.ux.uid = -1;
281 l->perm.ux.mode = 0;
282 uxst_add_listener(l);
283 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200284
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200285 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100286 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 } /* end for(port) */
288 } /* end while(next) */
289 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291 fail:
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294}
295
Willy Tarreau977b8e42006-12-29 14:19:17 +0100296/*
297 * Sends a warning if proxy <proxy> does not have at least one of the
298 * capabilities in <cap>. An optionnal <hint> may be added at the end
299 * of the warning to help the user. Returns 1 if a warning was emitted
300 * or 0 if the condition is valid.
301 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100302int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303{
304 char *msg;
305
306 switch (cap) {
307 case PR_CAP_BE: msg = "no backend"; break;
308 case PR_CAP_FE: msg = "no frontend"; break;
309 case PR_CAP_RS: msg = "no ruleset"; break;
310 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
311 default: msg = "not enough"; break;
312 }
313
314 if (!(proxy->cap & cap)) {
315 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100316 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100317 return 1;
318 }
319 return 0;
320}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200321
Willy Tarreau61d18892009-03-31 10:49:21 +0200322/* Report a warning if a rule is placed after a 'block' rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100325int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200326{
327 if (!LIST_ISEMPTY(&proxy->block_cond)) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
335/* Report a warning if a rule is placed after a reqrewrite rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
340 if (proxy->req_exp) {
341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
348/* Report a warning if a rule is placed after a reqadd rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100351int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200352{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100353 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200354 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
361/* Report a warning if a rule is placed after a redirect rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* Report a warning if a rule is placed after a 'use_backend' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
379 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
387/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100388int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200389{
390 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
391 warnif_rule_after_reqadd(proxy, file, line, arg) ||
392 warnif_rule_after_redirect(proxy, file, line, arg) ||
393 warnif_rule_after_use_backend(proxy, file, line, arg);
394}
395
396/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100397int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200398{
399 return 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 reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100405int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200406{
407 return warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100411/* Report it if a request ACL condition uses some response-only parameters. It
412 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
413 * Note that <cond> may be NULL and then will be ignored.
414 */
415static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
416{
417 struct acl *acl;
418
419 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
420 return 0;
421
422 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
423 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
424 file, line, acl ? acl->name : "(unknown)");
425 return ERR_WARN;
426}
427
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100428/* Report it if a request ACL condition uses some request-only volatile parameters.
429 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
430 * Note that <cond> may be NULL and then will be ignored.
431 */
432static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
433{
434 struct acl *acl;
435
436 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
437 return 0;
438
439 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
440 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
441 file, line, acl ? acl->name : "(unknown)");
442 return ERR_WARN;
443}
444
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100445
Willy Tarreaubaaee002006-06-26 02:48:02 +0200446/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200447 * parse a line in a <global> section. Returns the error code, 0 if OK, or
448 * any combination of :
449 * - ERR_ABORT: must abort ASAP
450 * - ERR_FATAL: we can continue parsing but not start the service
451 * - ERR_WARN: a warning has been emitted
452 * - ERR_ALERT: an alert has been emitted
453 * Only the two first ones can stop processing, the two others are just
454 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200456int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457{
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200459 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460
461 if (!strcmp(args[0], "global")) { /* new section */
462 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464 }
465 else if (!strcmp(args[0], "daemon")) {
466 global.mode |= MODE_DAEMON;
467 }
468 else if (!strcmp(args[0], "debug")) {
469 global.mode |= MODE_DEBUG;
470 }
471 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200473 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
477 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100483 else if (!strcmp(args[0], "nosplice")) {
484 global.tune.options &= ~GTUNE_USE_SPLICE;
485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "quiet")) {
487 global.mode |= MODE_QUIET;
488 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 else if (!strcmp(args[0], "tune.maxpollevents")) {
490 if (global.tune.maxpollevents != 0) {
491 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 if (*(args[1]) == 0) {
496 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT | ERR_FATAL;
498 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200499 }
500 global.tune.maxpollevents = atol(args[1]);
501 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 else if (!strcmp(args[0], "tune.maxaccept")) {
503 if (global.tune.maxaccept != 0) {
504 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 if (*(args[1]) == 0) {
509 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200510 err_code |= ERR_ALERT | ERR_FATAL;
511 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100512 }
513 global.tune.maxaccept = atol(args[1]);
514 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200515 else if (!strcmp(args[0], "tune.chksize")) {
516 if (*(args[1]) == 0) {
517 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
518 err_code |= ERR_ALERT | ERR_FATAL;
519 goto out;
520 }
521 global.tune.chksize = atol(args[1]);
522 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200523 else if (!strcmp(args[0], "tune.bufsize")) {
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.bufsize = atol(args[1]);
530 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
531 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200532 trashlen = global.tune.bufsize;
533 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200534 }
535 else if (!strcmp(args[0], "tune.maxrewrite")) {
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
540 }
541 global.tune.maxrewrite = atol(args[1]);
542 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
543 global.tune.maxrewrite = global.tune.bufsize / 2;
544 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100545 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
546 if (global.tune.client_rcvbuf != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT;
549 goto out;
550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
555 }
556 global.tune.client_rcvbuf = atol(args[1]);
557 }
558 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
559 if (global.tune.server_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.server_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.sndbuf.client")) {
572 if (global.tune.client_sndbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.client_sndbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.server")) {
585 if (global.tune.server_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.server_sndbuf = atol(args[1]);
596 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200597 else if (!strcmp(args[0], "tune.pipesize")) {
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.pipesize = atol(args[1]);
604 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200605 else if (!strcmp(args[0], "tune.http.maxhdr")) {
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.max_http_hdr = atol(args[1]);
612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 else if (!strcmp(args[0], "uid")) {
614 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200615 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 global.uid = atol(args[1]);
625 }
626 else if (!strcmp(args[0], "gid")) {
627 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 global.gid = atol(args[1]);
638 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200639 /* user/group name handling */
640 else if (!strcmp(args[0], "user")) {
641 struct passwd *ha_user;
642 if (global.uid != 0) {
643 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200644 err_code |= ERR_ALERT;
645 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200646 }
647 errno = 0;
648 ha_user = getpwnam(args[1]);
649 if (ha_user != NULL) {
650 global.uid = (int)ha_user->pw_uid;
651 }
652 else {
653 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 +0200654 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 }
656 }
657 else if (!strcmp(args[0], "group")) {
658 struct group *ha_group;
659 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200660 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
662 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200663 }
664 errno = 0;
665 ha_group = getgrnam(args[1]);
666 if (ha_group != NULL) {
667 global.gid = (int)ha_group->gr_gid;
668 }
669 else {
670 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 +0200671 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200672 }
673 }
674 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 else if (!strcmp(args[0], "nbproc")) {
676 if (global.nbproc != 0) {
677 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 if (*(args[1]) == 0) {
682 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 global.nbproc = atol(args[1]);
687 }
688 else if (!strcmp(args[0], "maxconn")) {
689 if (global.maxconn != 0) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.maxconn = atol(args[1]);
700#ifdef SYSTEM_MAXCONN
701 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
702 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);
703 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200705 }
706#endif /* SYSTEM_MAXCONN */
707 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200708 else if (!strcmp(args[0], "maxconnrate")) {
709 if (global.cps_lim != 0) {
710 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT;
712 goto out;
713 }
714 if (*(args[1]) == 0) {
715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 global.cps_lim = atol(args[1]);
720 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 else if (!strcmp(args[0], "maxpipes")) {
722 if (global.maxpipes != 0) {
723 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100731 }
732 global.maxpipes = atol(args[1]);
733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 else if (!strcmp(args[0], "ulimit-n")) {
735 if (global.rlimit_nofile != 0) {
736 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 if (*(args[1]) == 0) {
741 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 global.rlimit_nofile = atol(args[1]);
746 }
747 else if (!strcmp(args[0], "chroot")) {
748 if (global.chroot != NULL) {
749 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 if (*(args[1]) == 0) {
754 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 global.chroot = strdup(args[1]);
759 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200760 else if (!strcmp(args[0], "description")) {
761 int i, len=0;
762 char *d;
763
764 if (!*args[1]) {
765 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
766 file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770
771 for(i=1; *args[i]; i++)
772 len += strlen(args[i])+1;
773
774 if (global.desc)
775 free(global.desc);
776
777 global.desc = d = (char *)calloc(1, len);
778
779 d += sprintf(d, "%s", args[1]);
780 for(i=2; *args[i]; i++)
781 d += sprintf(d, " %s", args[i]);
782 }
783 else if (!strcmp(args[0], "node")) {
784 int i;
785 char c;
786
787 for (i=0; args[1][i]; i++) {
788 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100789 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
790 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200791 break;
792 }
793
794 if (!i || args[1][i]) {
795 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
796 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
797 file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801
802 if (global.node)
803 free(global.node);
804
805 global.node = strdup(args[1]);
806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 else if (!strcmp(args[0], "pidfile")) {
808 if (global.pidfile != NULL) {
809 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 global.pidfile = strdup(args[1]);
819 }
Emeric Bruned760922010-10-22 17:59:25 +0200820 else if (!strcmp(args[0], "unix-bind")) {
821 int cur_arg = 1;
822 while (*(args[cur_arg])) {
823 if (!strcmp(args[cur_arg], "prefix")) {
824 if (global.unix_bind.prefix != NULL) {
825 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
826 err_code |= ERR_ALERT;
827 cur_arg += 2;
828 continue;
829 }
830
831 if (*(args[cur_arg+1]) == 0) {
832 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836 global.unix_bind.prefix = strdup(args[cur_arg+1]);
837 cur_arg += 2;
838 continue;
839 }
840
841 if (!strcmp(args[cur_arg], "mode")) {
842
843 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
844 cur_arg += 2;
845 continue;
846 }
847
848 if (!strcmp(args[cur_arg], "uid")) {
849
850 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
851 cur_arg += 2;
852 continue;
853 }
854
855 if (!strcmp(args[cur_arg], "gid")) {
856
857 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
858 cur_arg += 2;
859 continue;
860 }
861
862 if (!strcmp(args[cur_arg], "user")) {
863 struct passwd *user;
864
865 user = getpwnam(args[cur_arg + 1]);
866 if (!user) {
867 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
868 file, linenum, args[0], args[cur_arg + 1 ]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872
873 global.unix_bind.ux.uid = user->pw_uid;
874 cur_arg += 2;
875 continue;
876 }
877
878 if (!strcmp(args[cur_arg], "group")) {
879 struct group *group;
880
881 group = getgrnam(args[cur_arg + 1]);
882 if (!group) {
883 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
884 file, linenum, args[0], args[cur_arg + 1 ]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888
889 global.unix_bind.ux.gid = group->gr_gid;
890 cur_arg += 2;
891 continue;
892 }
893
Willy Tarreaub48f9582011-09-05 01:17:06 +0200894 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200895 file, linenum, args[0]);
896 err_code |= ERR_ALERT | ERR_FATAL;
897 goto out;
898 }
899 }
William Lallemand0f99e342011-10-12 17:50:54 +0200900 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
901 /* delete previous herited or defined syslog servers */
902 struct logsrv *back;
903 struct logsrv *tmp;
904
905 if (*(args[1]) != 0) {
906 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910
911 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
912 LIST_DEL(&tmp->list);
913 free(tmp);
914 }
915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200917 struct logsrv *logsrv;
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 if (*(args[1]) == 0 || *(args[2]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
William Lallemand0f99e342011-10-12 17:50:54 +0200924
925 logsrv = calloc(1, sizeof(struct logsrv));
926
927 logsrv->facility = get_log_facility(args[2]);
928 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933
William Lallemand0f99e342011-10-12 17:50:54 +0200934 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->level = get_log_level(args[3]);
937 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200939 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941 }
942 }
943
William Lallemand0f99e342011-10-12 17:50:54 +0200944 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200946 logsrv->minlvl = get_log_level(args[4]);
947 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200948 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200950 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200951 }
952 }
953
Robert Tsai81ae1952007-12-05 10:47:29 +0100954 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100955 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 if (!sk) {
957 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100958 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100959 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200960 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 goto out;
962 }
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100964 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100965 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100966 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100967 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
968 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200969 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100970 goto out;
971 }
William Lallemand0f99e342011-10-12 17:50:54 +0200972 logsrv->addr = *sk;
973 if (!get_host_port(&logsrv->addr))
974 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976
William Lallemand0f99e342011-10-12 17:50:54 +0200977 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200978 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100979 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
980 char *name;
981 int len;
982
983 if (global.log_send_hostname != NULL) {
984 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT;
986 goto out;
987 }
988
989 if (*(args[1]))
990 name = args[1];
991 else
992 name = hostname;
993
994 len = strlen(name);
995
996 /* We'll add a space after the name to respect the log format */
997 free(global.log_send_hostname);
998 global.log_send_hostname = malloc(len + 2);
999 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1000 }
Kevinm48936af2010-12-22 16:08:21 +00001001 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1002 if (*(args[1]) == 0) {
1003 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1004 err_code |= ERR_ALERT | ERR_FATAL;
1005 goto out;
1006 }
1007 free(global.log_tag);
1008 global.log_tag = strdup(args[1]);
1009 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1011 if (global.spread_checks != 0) {
1012 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 if (*(args[1]) == 0) {
1017 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
1021 global.spread_checks = atol(args[1]);
1022 if (global.spread_checks < 0 || global.spread_checks > 50) {
1023 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 }
1027 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001028 struct cfg_kw_list *kwl;
1029 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001031
1032 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1033 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1034 if (kwl->kw[index].section != CFG_GLOBAL)
1035 continue;
1036 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1037 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001038 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001040 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001041 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001042 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001043 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001045 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001046 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_WARN;
1048 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001049 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001051 }
1052 }
1053 }
1054
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001058
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001060 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062}
1063
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001064void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001066 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 defproxy.mode = PR_MODE_TCP;
1068 defproxy.state = PR_STNEW;
1069 defproxy.maxconn = cfg_maxpconn;
1070 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001071
1072 defproxy.defsrv.inter = DEF_CHKINTR;
1073 defproxy.defsrv.fastinter = 0;
1074 defproxy.defsrv.downinter = 0;
1075 defproxy.defsrv.rise = DEF_RISETIME;
1076 defproxy.defsrv.fall = DEF_FALLTIME;
1077 defproxy.defsrv.check_port = 0;
1078 defproxy.defsrv.maxqueue = 0;
1079 defproxy.defsrv.minconn = 0;
1080 defproxy.defsrv.maxconn = 0;
1081 defproxy.defsrv.slowstart = 0;
1082 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1083 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1084 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085}
1086
Willy Tarreauade5ec42010-01-28 19:33:49 +01001087
1088static int create_cond_regex_rule(const char *file, int line,
1089 struct proxy *px, int dir, int action, int flags,
1090 const char *cmd, const char *reg, const char *repl,
1091 const char **cond_start)
1092{
1093 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001094 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001095 const char *err;
1096 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001097 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001098
1099 if (px == &defproxy) {
1100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto err;
1103 }
1104
1105 if (*reg == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto err;
1109 }
1110
1111 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1112 err_code |= ERR_WARN;
1113
Willy Tarreau5321c422010-01-28 20:35:13 +01001114 if (cond_start &&
1115 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001116 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1117 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1118 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto err;
1121 }
1122 }
1123 else if (cond_start && **cond_start) {
1124 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1125 file, line, cmd, *cond_start);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto err;
1128 }
1129
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001130 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001131 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001132 else
1133 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001134
Willy Tarreauade5ec42010-01-28 19:33:49 +01001135 preg = calloc(1, sizeof(regex_t));
1136 if (!preg) {
1137 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1138 err_code = ERR_ALERT | ERR_FATAL;
1139 goto err;
1140 }
1141
1142 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1143 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1144 err_code = ERR_ALERT | ERR_FATAL;
1145 goto err;
1146 }
1147
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001148 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001149 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001150 if (repl && err) {
1151 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1152 file, line, cmd, *err);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto err;
1155 }
1156
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001157 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001158 err_code |= ERR_WARN;
1159
Willy Tarreauf4068b62012-05-08 17:37:49 +02001160 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001161 return err_code;
1162 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001163 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001164 free(preg);
1165 return err_code;
1166}
1167
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001169 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001170 * Returns the error code, 0 if OK, or any combination of :
1171 * - ERR_ABORT: must abort ASAP
1172 * - ERR_FATAL: we can continue parsing but not start the service
1173 * - ERR_WARN: a warning has been emitted
1174 * - ERR_ALERT: an alert has been emitted
1175 * Only the two first ones can stop processing, the two others are just
1176 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001178int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1179{
1180 static struct peers *curpeers = NULL;
1181 struct peer *newpeer = NULL;
1182 const char *err;
1183 int err_code = 0;
1184
1185 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1186
1187 err = invalid_char(args[1]);
1188 if (err) {
1189 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1190 file, linenum, *err, args[0], args[1]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 }
1193
1194 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1195 /*
1196 * If there are two proxies with the same name only following
1197 * combinations are allowed:
1198 */
1199 if (strcmp(curpeers->id, args[1]) == 0) {
1200 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1201 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1202 err_code |= ERR_WARN;
1203 }
1204 }
1205
1206 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1207 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1208 err_code |= ERR_ALERT | ERR_ABORT;
1209 goto out;
1210 }
1211
1212 curpeers->next = peers;
1213 peers = curpeers;
1214 curpeers->conf.file = file;
1215 curpeers->conf.line = linenum;
1216 curpeers->last_change = now.tv_sec;
1217 curpeers->id = strdup(args[1]);
1218 }
1219 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1220 char *rport, *raddr;
1221 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001222 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001223
1224 if (!*args[2]) {
1225 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1226 file, linenum, args[0]);
1227 err_code |= ERR_ALERT | ERR_FATAL;
1228 goto out;
1229 }
1230
1231 err = invalid_char(args[1]);
1232 if (err) {
1233 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1234 file, linenum, *err, args[1]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1241 err_code |= ERR_ALERT | ERR_ABORT;
1242 goto out;
1243 }
1244
1245 /* the peers are linked backwards first */
1246 curpeers->count++;
1247 newpeer->next = curpeers->remote;
1248 curpeers->remote = newpeer;
1249 newpeer->peers = curpeers;
1250 newpeer->conf.file = file;
1251 newpeer->conf.line = linenum;
1252
1253 newpeer->last_change = now.tv_sec;
1254 newpeer->id = strdup(args[1]);
1255
1256 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001257 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001258 if (rport) {
1259 *rport++ = 0;
1260 realport = atol(rport);
1261 }
1262 if (!realport) {
1263 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266 }
1267
Willy Tarreaufab5a432011-03-04 15:31:53 +01001268 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001269 free(raddr);
1270 if (!sk) {
1271 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001276 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02001277 newpeer->sock = &sock_raw;
1278 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001279
1280 if (!sk) {
1281 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1282 file, linenum, newpeer->addr.ss_family, args[2]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
1286
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001287 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001288
1289 if (strcmp(newpeer->id, localpeer) == 0) {
1290 /* Current is local peer, it define a frontend */
1291 newpeer->local = 1;
1292
1293 if (!curpeers->peers_fe) {
1294 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1296 err_code |= ERR_ALERT | ERR_ABORT;
1297 goto out;
1298 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001299
Willy Tarreau237250c2011-07-29 01:49:03 +02001300 init_new_proxy(curpeers->peers_fe);
1301 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001302
1303 curpeers->peers_fe->last_change = now.tv_sec;
1304 curpeers->peers_fe->id = strdup(args[1]);
1305 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001306 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001307 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1308 curpeers->peers_fe->timeout.connect = 5000;
1309 curpeers->peers_fe->accept = peer_accept;
1310 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001311 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001312 err_code |= ERR_FATAL;
1313 goto out;
1314 }
1315 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1316 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1317 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1318 curpeers->peers_fe->listen->accept = session_accept;
1319 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1320 curpeers->peers_fe->listen->handler = process_session;
1321 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001322 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1323 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001324 }
1325 }
1326 } /* neither "peer" nor "peers" */
1327 else if (*args[0] != 0) {
1328 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto out;
1331 }
1332
1333out:
1334 return err_code;
1335}
1336
1337
Willy Tarreau3842f002009-06-14 11:39:52 +02001338int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339{
1340 static struct proxy *curproxy = NULL;
1341 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001342 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001343 int rc;
1344 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001345 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001346 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001347 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001348 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349
Willy Tarreau977b8e42006-12-29 14:19:17 +01001350 if (!strcmp(args[0], "listen"))
1351 rc = PR_CAP_LISTEN;
1352 else if (!strcmp(args[0], "frontend"))
1353 rc = PR_CAP_FE | PR_CAP_RS;
1354 else if (!strcmp(args[0], "backend"))
1355 rc = PR_CAP_BE | PR_CAP_RS;
1356 else if (!strcmp(args[0], "ruleset"))
1357 rc = PR_CAP_RS;
1358 else
1359 rc = PR_CAP_NONE;
1360
1361 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362 if (!*args[1]) {
1363 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1364 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1365 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_ABORT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001369
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001370 err = invalid_char(args[1]);
1371 if (err) {
1372 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1373 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001375 }
1376
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001377 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1378 /*
1379 * If there are two proxies with the same name only following
1380 * combinations are allowed:
1381 *
1382 * listen backend frontend ruleset
1383 * listen - - - -
1384 * backend - - OK -
1385 * frontend - OK - -
1386 * ruleset - - - -
1387 */
1388
1389 if (!strcmp(curproxy->id, args[1]) &&
1390 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1391 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001392 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1393 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1394 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001395 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001396 }
1397 }
1398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
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 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001404
Willy Tarreau97cb7802010-01-03 20:23:58 +01001405 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 curproxy->next = proxy;
1407 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001408 curproxy->conf.file = file;
1409 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001410 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001412 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413
1414 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001415 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001416 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001417 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001418 err_code |= ERR_FATAL;
1419 goto out;
1420 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001421 new = curproxy->listen;
1422 while (new != last) {
1423 new->conf.file = file;
1424 new->conf.line = linenum;
1425 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001426 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 }
1429
1430 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001431 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001432 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001433
Willy Tarreaubaaee002006-06-26 02:48:02 +02001434 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001436 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001437 curproxy->no_options = defproxy.no_options;
1438 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001439 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001440 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001441 curproxy->except_net = defproxy.except_net;
1442 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001443 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001444 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001446 if (defproxy.fwdfor_hdr_len) {
1447 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1448 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1449 }
1450
Willy Tarreaub86db342009-11-30 11:50:16 +01001451 if (defproxy.orgto_hdr_len) {
1452 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1453 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1454 }
1455
Mark Lamourinec2247f02012-01-04 13:02:01 -05001456 if (defproxy.server_id_hdr_len) {
1457 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1458 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1459 }
1460
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 if (curproxy->cap & PR_CAP_FE) {
1462 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001463 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001464 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465
1466 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001467 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1468 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469
1470 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1471 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 if (curproxy->cap & PR_CAP_BE) {
1474 curproxy->fullconn = defproxy.fullconn;
1475 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001477 if (defproxy.check_req) {
1478 curproxy->check_req = calloc(1, defproxy.check_len);
1479 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1480 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001483 if (defproxy.expect_str) {
1484 curproxy->expect_str = strdup(defproxy.expect_str);
1485 if (defproxy.expect_regex) {
1486 /* note: this regex is known to be valid */
1487 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1488 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1489 }
1490 }
1491
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 if (defproxy.cookie_name)
1493 curproxy->cookie_name = strdup(defproxy.cookie_name);
1494 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001495 if (defproxy.cookie_domain)
1496 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001497
Willy Tarreau31936852010-10-06 16:59:56 +02001498 if (defproxy.cookie_maxidle)
1499 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1500
1501 if (defproxy.cookie_maxlife)
1502 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1503
Emeric Brun647caf12009-06-30 17:57:00 +02001504 if (defproxy.rdp_cookie_name)
1505 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1506 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1507
Willy Tarreau01732802007-11-01 22:48:15 +01001508 if (defproxy.url_param_name)
1509 curproxy->url_param_name = strdup(defproxy.url_param_name);
1510 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001511
Benoitaffb4812009-03-25 13:02:10 +01001512 if (defproxy.hh_name)
1513 curproxy->hh_name = strdup(defproxy.hh_name);
1514 curproxy->hh_len = defproxy.hh_len;
1515 curproxy->hh_match_domain = defproxy.hh_match_domain;
1516
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001517 if (defproxy.iface_name)
1518 curproxy->iface_name = strdup(defproxy.iface_name);
1519 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001522 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 if (defproxy.capture_name)
1524 curproxy->capture_name = strdup(defproxy.capture_name);
1525 curproxy->capture_namelen = defproxy.capture_namelen;
1526 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528
Willy Tarreau977b8e42006-12-29 14:19:17 +01001529 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001530 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001531 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001532 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001533 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001534 curproxy->uri_auth = defproxy.uri_auth;
1535 curproxy->mon_net = defproxy.mon_net;
1536 curproxy->mon_mask = defproxy.mon_mask;
1537 if (defproxy.monitor_uri)
1538 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1539 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001540 if (defproxy.defbe.name)
1541 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001542 }
1543
1544 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001545 curproxy->timeout.connect = defproxy.timeout.connect;
1546 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001547 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001548 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001549 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001550 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001551 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001552 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 curproxy->source_addr = defproxy.source_addr;
1554 }
1555
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001557
1558 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001559 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001560 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001561 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001562 LIST_INIT(&node->list);
1563 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1564 }
1565
Willy Tarreau196729e2012-05-31 19:30:26 +02001566 /* get either a pointer to the logformat string or a copy of it */
1567 curproxy->logformat_string = defproxy.logformat_string;
1568 if (curproxy->logformat_string &&
1569 curproxy->logformat_string != default_http_log_format &&
1570 curproxy->logformat_string != default_tcp_log_format &&
1571 curproxy->logformat_string != clf_http_log_format)
1572 curproxy->logformat_string = strdup(curproxy->logformat_string);
William Lallemand723b73a2012-02-08 16:37:49 +01001573
Willy Tarreau196729e2012-05-31 19:30:26 +02001574 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1575 if (curproxy->uniqueid_format_string)
1576 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001577
1578 /* copy default header unique id */
1579 if (defproxy.header_unique_id)
1580 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1581
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001583 curproxy->conf.used_listener_id = EB_ROOT;
1584 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001585
Willy Tarreau93893792009-07-23 13:19:11 +02001586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
1588 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1589 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001590 /* FIXME-20070101: we should do this too at the end of the
1591 * config parsing to free all default values.
1592 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001593 free(defproxy.check_req);
1594 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001595 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001596 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001597 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001598 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(defproxy.capture_name);
1600 free(defproxy.monitor_uri);
1601 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001602 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001603 free(defproxy.fwdfor_hdr_name);
1604 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001605 free(defproxy.orgto_hdr_name);
1606 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001607 free(defproxy.server_id_hdr_name);
1608 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001609 free(defproxy.expect_str);
1610 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001611
Willy Tarreau196729e2012-05-31 19:30:26 +02001612 if (defproxy.logformat_string == default_http_log_format ||
1613 defproxy.logformat_string == default_tcp_log_format ||
1614 defproxy.logformat_string == clf_http_log_format)
1615 free(defproxy.logformat_string);
1616
1617 free(defproxy.uniqueid_format_string);
1618
Willy Tarreaua534fea2008-08-03 12:19:50 +02001619 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001620 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001621
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 /* we cannot free uri_auth because it might already be used */
1623 init_default_instance();
1624 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001625 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 }
1628 else if (curproxy == NULL) {
1629 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 }
1633
Willy Tarreau977b8e42006-12-29 14:19:17 +01001634
1635 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001637 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001638 int cur_arg;
1639
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 if (curproxy == &defproxy) {
1641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001645 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647
Emeric Bruned760922010-10-22 17:59:25 +02001648 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001649 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001654
1655 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001656
1657 /* NOTE: the following line might create several listeners if there
1658 * are comma-separated IPs or port ranges. So all further processing
1659 * will have to be applied to all listeners created after last_listen.
1660 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001661 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001665
Willy Tarreau90a570f2009-10-04 20:54:54 +02001666 new_listen = curproxy->listen;
1667 while (new_listen != last_listen) {
1668 new_listen->conf.file = file;
1669 new_listen->conf.line = linenum;
1670 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001671 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001672 }
1673
Emeric Bruned760922010-10-22 17:59:25 +02001674 /* Set default global rights and owner for unix bind */
1675 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1676 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1677 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001678 cur_arg = 2;
1679 while (*(args[cur_arg])) {
1680 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1681#ifdef SO_BINDTODEVICE
1682 struct listener *l;
1683
Emeric Bruned760922010-10-22 17:59:25 +02001684 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1685 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1686 file, linenum, args[0], args[cur_arg]);
1687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
1689 }
1690
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001691 if (!*args[cur_arg + 1]) {
1692 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001696 }
1697
1698 for (l = curproxy->listen; l != last_listen; l = l->next)
1699 l->interface = strdup(args[cur_arg + 1]);
1700
1701 global.last_checks |= LSTCHK_NETADM;
1702
1703 cur_arg += 2;
1704 continue;
1705#else
1706 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1707 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001710#endif
1711 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001712 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1713#ifdef TCP_MAXSEG
1714 struct listener *l;
1715 int mss;
1716
Emeric Bruned760922010-10-22 17:59:25 +02001717 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1719 file, linenum, args[0], args[cur_arg]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
Willy Tarreaube1b9182009-06-14 18:48:19 +02001724 if (!*args[cur_arg + 1]) {
1725 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001729 }
1730
Willy Tarreau48a7e722010-12-24 15:26:39 +01001731 mss = atoi(args[cur_arg + 1]);
1732 if (!mss || abs(mss) > 65535) {
1733 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001734 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001737 }
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->maxseg = mss;
1741
1742 cur_arg += 2;
1743 continue;
1744#else
1745 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1746 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001749#endif
1750 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001751
1752 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1753#ifdef TCP_DEFER_ACCEPT
1754 struct listener *l;
1755
1756 for (l = curproxy->listen; l != last_listen; l = l->next)
1757 l->options |= LI_O_DEF_ACCEPT;
1758
1759 cur_arg ++;
1760 continue;
1761#else
1762 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1763 file, linenum, args[0], args[cur_arg]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766#endif
1767 }
1768
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001769 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001770#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001771 struct listener *l;
1772
Emeric Bruned760922010-10-22 17:59:25 +02001773 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1774 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1775 file, linenum, args[0], args[cur_arg]);
1776 err_code |= ERR_ALERT | ERR_FATAL;
1777 goto out;
1778 }
1779
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001780 for (l = curproxy->listen; l != last_listen; l = l->next)
1781 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001782
1783 cur_arg ++;
1784 continue;
1785#else
1786 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1787 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001790#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001791 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001792
Willy Tarreau8a956912010-10-15 14:27:08 +02001793 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1794 struct listener *l;
1795
1796 for (l = curproxy->listen; l != last_listen; l = l->next)
1797 l->options |= LI_O_ACC_PROXY;
1798
1799 cur_arg ++;
1800 continue;
1801 }
1802
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001803 if (!strcmp(args[cur_arg], "name")) {
1804 struct listener *l;
1805
1806 for (l = curproxy->listen; l != last_listen; l = l->next)
1807 l->name = strdup(args[cur_arg + 1]);
1808
1809 cur_arg += 2;
1810 continue;
1811 }
1812
1813 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001814 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001815 struct listener *l;
1816
1817 if (curproxy->listen->next != last_listen) {
1818 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1819 file, linenum, args[cur_arg]);
1820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
1822 }
1823
1824 if (!*args[cur_arg + 1]) {
1825 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1826 file, linenum, args[cur_arg]);
1827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
1830
1831 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001832 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001833
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001834 if (curproxy->listen->luid <= 0) {
1835 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001836 file, linenum);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001841 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1842 if (node) {
1843 l = container_of(node, struct listener, conf.id);
1844 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1845 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
1848 }
1849 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1850
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001851 cur_arg += 2;
1852 continue;
1853 }
1854
Emeric Bruned760922010-10-22 17:59:25 +02001855 if (!strcmp(args[cur_arg], "mode")) {
1856
1857 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1858 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1859 file, linenum, args[0], args[cur_arg]);
1860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
1862 }
1863
1864 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1865
1866 cur_arg += 2;
1867 continue;
1868 }
1869
1870 if (!strcmp(args[cur_arg], "uid")) {
1871
1872 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1873 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1874 file, linenum, args[0], args[cur_arg]);
1875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
1877 }
1878
1879 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1880 cur_arg += 2;
1881 continue;
1882 }
1883
1884 if (!strcmp(args[cur_arg], "gid")) {
1885
1886 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1887 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1888 file, linenum, args[0], args[cur_arg]);
1889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
1891 }
1892
1893 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1894 cur_arg += 2;
1895 continue;
1896 }
1897
1898 if (!strcmp(args[cur_arg], "user")) {
1899 struct passwd *user;
1900
1901 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1902 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1903 file, linenum, args[0], args[cur_arg]);
1904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
1906 }
1907 user = getpwnam(args[cur_arg + 1]);
1908 if (!user) {
1909 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1910 file, linenum, args[0], args[cur_arg + 1 ]);
1911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
1913 }
1914
1915 curproxy->listen->perm.ux.uid = user->pw_uid;
1916 cur_arg += 2;
1917 continue;
1918 }
1919
1920 if (!strcmp(args[cur_arg], "group")) {
1921 struct group *group;
1922
1923 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1924 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1925 file, linenum, args[0], args[cur_arg]);
1926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
1928 }
1929 group = getgrnam(args[cur_arg + 1]);
1930 if (!group) {
1931 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1932 file, linenum, args[0], args[cur_arg + 1 ]);
1933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
1935 }
1936
1937 curproxy->listen->perm.ux.gid = group->gr_gid;
1938 cur_arg += 2;
1939 continue;
1940 }
1941
Willy Tarreaub48f9582011-09-05 01:17:06 +02001942 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 +01001943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001946 }
Willy Tarreau93893792009-07-23 13:19:11 +02001947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 }
1949 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1950 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1951 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1952 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001956 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 /* flush useless bits */
1960 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001963 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001966
Willy Tarreau1c47f852006-07-09 08:22:27 +02001967 if (!*args[1]) {
1968 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001972 }
1973
Willy Tarreaua534fea2008-08-03 12:19:50 +02001974 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001975 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001976 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001977 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001978 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1979
Willy Tarreau93893792009-07-23 13:19:11 +02001980 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001982 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1983 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1984 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1985 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1986 else {
1987 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 }
1991 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001992 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001993 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994
1995 if (curproxy == &defproxy) {
1996 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1997 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001998 err_code |= ERR_ALERT | ERR_FATAL;
1999 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002000 }
2001
2002 if (!*args[1]) {
2003 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2004 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002007 }
2008
2009 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002010 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002011
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002012 if (curproxy->uuid <= 0) {
2013 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002014 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_ALERT | ERR_FATAL;
2016 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002017 }
2018
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002019 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2020 if (node) {
2021 struct proxy *target = container_of(node, struct proxy, conf.id);
2022 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2023 file, linenum, proxy_type_str(curproxy), curproxy->id,
2024 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2025 err_code |= ERR_ALERT | ERR_FATAL;
2026 goto out;
2027 }
2028 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002029 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002030 else if (!strcmp(args[0], "description")) {
2031 int i, len=0;
2032 char *d;
2033
Cyril Bonté99ed3272010-01-24 23:29:44 +01002034 if (curproxy == &defproxy) {
2035 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2036 file, linenum, args[0]);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002041 if (!*args[1]) {
2042 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2043 file, linenum, args[0]);
2044 return -1;
2045 }
2046
2047 for(i=1; *args[i]; i++)
2048 len += strlen(args[i])+1;
2049
2050 d = (char *)calloc(1, len);
2051 curproxy->desc = d;
2052
2053 d += sprintf(d, "%s", args[1]);
2054 for(i=2; *args[i]; i++)
2055 d += sprintf(d, " %s", args[i]);
2056
2057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2059 curproxy->state = PR_STSTOPPED;
2060 }
2061 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2062 curproxy->state = PR_STNEW;
2063 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002064 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2065 int cur_arg = 1;
2066 unsigned int set = 0;
2067
2068 while (*args[cur_arg]) {
2069 int u;
2070 if (strcmp(args[cur_arg], "all") == 0) {
2071 set = 0;
2072 break;
2073 }
2074 else if (strcmp(args[cur_arg], "odd") == 0) {
2075 set |= 0x55555555;
2076 }
2077 else if (strcmp(args[cur_arg], "even") == 0) {
2078 set |= 0xAAAAAAAA;
2079 }
2080 else {
2081 u = str2uic(args[cur_arg]);
2082 if (u < 1 || u > 32) {
2083 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002087 }
2088 if (u > global.nbproc) {
2089 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2090 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002092 }
2093 set |= 1 << (u - 1);
2094 }
2095 cur_arg++;
2096 }
2097 curproxy->bind_proc = set;
2098 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002099 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002100 if (curproxy == &defproxy) {
2101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002104 }
2105
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002106 err = invalid_char(args[1]);
2107 if (err) {
2108 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2109 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002111 }
2112
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002113 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2114 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2115 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002116 err_code |= ERR_ALERT | ERR_FATAL;
2117 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002118 }
2119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2121 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122
Willy Tarreau977b8e42006-12-29 14:19:17 +01002123 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 if (*(args[1]) == 0) {
2127 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2128 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002132
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002133 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002134 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002135 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002136 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002137 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 curproxy->cookie_name = strdup(args[1]);
2139 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002140
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 cur_arg = 2;
2142 while (*(args[cur_arg])) {
2143 if (!strcmp(args[cur_arg], "rewrite")) {
2144 curproxy->options |= PR_O_COOK_RW;
2145 }
2146 else if (!strcmp(args[cur_arg], "indirect")) {
2147 curproxy->options |= PR_O_COOK_IND;
2148 }
2149 else if (!strcmp(args[cur_arg], "insert")) {
2150 curproxy->options |= PR_O_COOK_INS;
2151 }
2152 else if (!strcmp(args[cur_arg], "nocache")) {
2153 curproxy->options |= PR_O_COOK_NOC;
2154 }
2155 else if (!strcmp(args[cur_arg], "postonly")) {
2156 curproxy->options |= PR_O_COOK_POST;
2157 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002158 else if (!strcmp(args[cur_arg], "preserve")) {
2159 curproxy->options2 |= PR_O2_COOK_PSV;
2160 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 else if (!strcmp(args[cur_arg], "prefix")) {
2162 curproxy->options |= PR_O_COOK_PFX;
2163 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002164 else if (!strcmp(args[cur_arg], "domain")) {
2165 if (!*args[cur_arg + 1]) {
2166 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2167 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002170 }
2171
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002172 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002173 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002174 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2175 " dots nor does not start with a dot."
2176 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002177 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002178 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002179 }
2180
2181 err = invalid_domainchar(args[cur_arg + 1]);
2182 if (err) {
2183 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2184 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002187 }
2188
Willy Tarreau68a897b2009-12-03 23:28:34 +01002189 if (!curproxy->cookie_domain) {
2190 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2191 } else {
2192 /* one domain was already specified, add another one by
2193 * building the string which will be returned along with
2194 * the cookie.
2195 */
2196 char *new_ptr;
2197 int new_len = strlen(curproxy->cookie_domain) +
2198 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2199 new_ptr = malloc(new_len);
2200 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2201 free(curproxy->cookie_domain);
2202 curproxy->cookie_domain = new_ptr;
2203 }
Willy Tarreau31936852010-10-06 16:59:56 +02002204 cur_arg++;
2205 }
2206 else if (!strcmp(args[cur_arg], "maxidle")) {
2207 unsigned int maxidle;
2208 const char *res;
2209
2210 if (!*args[cur_arg + 1]) {
2211 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2212 file, linenum, args[cur_arg]);
2213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
2215 }
2216
2217 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2218 if (res) {
2219 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2220 file, linenum, *res, args[cur_arg]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224 curproxy->cookie_maxidle = maxidle;
2225 cur_arg++;
2226 }
2227 else if (!strcmp(args[cur_arg], "maxlife")) {
2228 unsigned int maxlife;
2229 const char *res;
2230
2231 if (!*args[cur_arg + 1]) {
2232 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2233 file, linenum, args[cur_arg]);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
2236 }
2237
2238 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2239 if (res) {
2240 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2241 file, linenum, *res, args[cur_arg]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002246 cur_arg++;
2247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002249 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 +02002250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
2254 cur_arg++;
2255 }
2256 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2257 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
2261
2262 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2263 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2264 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002267
2268 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2269 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2270 file, linenum);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002274 else if (!strcmp(args[0], "persist")) { /* persist */
2275 if (*(args[1]) == 0) {
2276 Alert("parsing [%s:%d] : missing persist method.\n",
2277 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002280 }
2281
2282 if (!strncmp(args[1], "rdp-cookie", 10)) {
2283 curproxy->options2 |= PR_O2_RDPC_PRST;
2284
Emeric Brunb982a3d2010-01-04 15:45:53 +01002285 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002286 const char *beg, *end;
2287
2288 beg = args[1] + 11;
2289 end = strchr(beg, ')');
2290
2291 if (!end || end == beg) {
2292 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2293 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002296 }
2297
2298 free(curproxy->rdp_cookie_name);
2299 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2300 curproxy->rdp_cookie_len = end-beg;
2301 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002302 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002303 free(curproxy->rdp_cookie_name);
2304 curproxy->rdp_cookie_name = strdup("msts");
2305 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2306 }
2307 else { /* syntax */
2308 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002312 }
2313 }
2314 else {
2315 Alert("parsing [%s:%d] : unknown persist method.\n",
2316 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002319 }
2320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002322 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002324 if (curproxy == &defproxy) {
2325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
Willy Tarreau977b8e42006-12-29 14:19:17 +01002330 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002334 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 }
2339 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002340 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 curproxy->appsession_name = strdup(args[1]);
2342 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2343 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002344 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2345 if (err) {
2346 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2347 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002350 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002351 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002352
Willy Tarreau51041c72007-09-09 21:56:53 +02002353 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2354 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_ALERT | ERR_ABORT;
2356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002358
2359 cur_arg = 6;
2360 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002361 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2362 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002363 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002364 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002365 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002366 } else if (!strcmp(args[cur_arg], "prefix")) {
2367 curproxy->options2 |= PR_O2_AS_PFX;
2368 } else if (!strcmp(args[cur_arg], "mode")) {
2369 if (!*args[cur_arg + 1]) {
2370 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2371 file, linenum, args[0], args[cur_arg]);
2372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
2374 }
2375
2376 cur_arg++;
2377 if (!strcmp(args[cur_arg], "query-string")) {
2378 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2379 curproxy->options2 |= PR_O2_AS_M_QS;
2380 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2381 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2382 curproxy->options2 |= PR_O2_AS_M_PP;
2383 } else {
2384 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
2387 }
2388 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002389 cur_arg++;
2390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 } /* Url App Session */
2392 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002393 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002395
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002397 if (curproxy == &defproxy) {
2398 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 if (*(args[4]) == 0) {
2404 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2405 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002409 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 curproxy->capture_name = strdup(args[2]);
2411 curproxy->capture_namelen = strlen(curproxy->capture_name);
2412 curproxy->capture_len = atol(args[4]);
2413 if (curproxy->capture_len >= CAPTURE_LEN) {
2414 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2415 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 curproxy->capture_len = CAPTURE_LEN - 1;
2418 }
2419 curproxy->to_log |= LW_COOKIE;
2420 }
2421 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2422 struct cap_hdr *hdr;
2423
2424 if (curproxy == &defproxy) {
2425 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 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
2429
2430 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2431 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2432 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436
2437 hdr = calloc(sizeof(struct cap_hdr), 1);
2438 hdr->next = curproxy->req_cap;
2439 hdr->name = strdup(args[3]);
2440 hdr->namelen = strlen(args[3]);
2441 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002442 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 hdr->index = curproxy->nb_req_cap++;
2444 curproxy->req_cap = hdr;
2445 curproxy->to_log |= LW_REQHDR;
2446 }
2447 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2448 struct cap_hdr *hdr;
2449
2450 if (curproxy == &defproxy) {
2451 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 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
2455
2456 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2457 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2458 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462 hdr = calloc(sizeof(struct cap_hdr), 1);
2463 hdr->next = curproxy->rsp_cap;
2464 hdr->name = strdup(args[3]);
2465 hdr->namelen = strlen(args[3]);
2466 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002467 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 hdr->index = curproxy->nb_rsp_cap++;
2469 curproxy->rsp_cap = hdr;
2470 curproxy->to_log |= LW_RSPHDR;
2471 }
2472 else {
2473 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2474 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 }
2478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002480 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002482
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 if (*(args[1]) == 0) {
2484 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2485 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }
2489 curproxy->conn_retries = atol(args[1]);
2490 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002491 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002492 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002493
2494 if (curproxy == &defproxy) {
2495 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499
Willy Tarreauff011f22011-01-06 17:51:27 +01002500 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 +01002501 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2502 file, linenum, args[0]);
2503 err_code |= ERR_WARN;
2504 }
2505
Willy Tarreauff011f22011-01-06 17:51:27 +01002506 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002507
Willy Tarreauff011f22011-01-06 17:51:27 +01002508 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002509 err_code |= ERR_ALERT | ERR_ABORT;
2510 goto out;
2511 }
2512
Willy Tarreauff011f22011-01-06 17:51:27 +01002513 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2514 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002515 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002516 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2517 /* set the header name and length into the proxy structure */
2518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2519 err_code |= ERR_WARN;
2520
2521 if (!*args[1]) {
2522 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2523 file, linenum, args[0]);
2524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
2526 }
2527
2528 /* set the desired header name */
2529 free(curproxy->server_id_hdr_name);
2530 curproxy->server_id_hdr_name = strdup(args[1]);
2531 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2532 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002533 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002538 }
2539
Willy Tarreauef6494c2010-01-28 17:12:36 +01002540 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002541 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002545 }
2546
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002547 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2548 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2549 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002552 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002553
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002554 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002555 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002556 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002558 struct redirect_rule *rule;
2559 int cur_arg;
2560 int type = REDIRECT_TYPE_NONE;
2561 int code = 302;
2562 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002563 char *cookie = NULL;
2564 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002565 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002566
Cyril Bonté99ed3272010-01-24 23:29:44 +01002567 if (curproxy == &defproxy) {
2568 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
2571 }
2572
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002573 cur_arg = 1;
2574 while (*(args[cur_arg])) {
2575 if (!strcmp(args[cur_arg], "location")) {
2576 if (!*args[cur_arg + 1]) {
2577 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2578 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002581 }
2582
2583 type = REDIRECT_TYPE_LOCATION;
2584 cur_arg++;
2585 destination = args[cur_arg];
2586 }
2587 else if (!strcmp(args[cur_arg], "prefix")) {
2588 if (!*args[cur_arg + 1]) {
2589 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2590 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 }
2594
2595 type = REDIRECT_TYPE_PREFIX;
2596 cur_arg++;
2597 destination = args[cur_arg];
2598 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002599 else if (!strcmp(args[cur_arg], "set-cookie")) {
2600 if (!*args[cur_arg + 1]) {
2601 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2602 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002605 }
2606
2607 cur_arg++;
2608 cookie = args[cur_arg];
2609 cookie_set = 1;
2610 }
2611 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2612 if (!*args[cur_arg + 1]) {
2613 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2614 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002617 }
2618
2619 cur_arg++;
2620 cookie = args[cur_arg];
2621 cookie_set = 0;
2622 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002623 else if (!strcmp(args[cur_arg],"code")) {
2624 if (!*args[cur_arg + 1]) {
2625 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002629 }
2630 cur_arg++;
2631 code = atol(args[cur_arg]);
2632 if (code < 301 || code > 303) {
2633 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2634 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002637 }
2638 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002639 else if (!strcmp(args[cur_arg],"drop-query")) {
2640 flags |= REDIRECT_FLAG_DROP_QS;
2641 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002642 else if (!strcmp(args[cur_arg],"append-slash")) {
2643 flags |= REDIRECT_FLAG_APPEND_SLASH;
2644 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 else if (strcmp(args[cur_arg], "if") == 0 ||
2646 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002647 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002648 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002649 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2650 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002654 break;
2655 }
2656 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002657 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661 }
2662 cur_arg++;
2663 }
2664
2665 if (type == REDIRECT_TYPE_NONE) {
2666 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002670 }
2671
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2673 rule->cond = cond;
2674 rule->rdr_str = strdup(destination);
2675 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002676 if (cookie) {
2677 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002678 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002679 */
2680 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002681 if (cookie_set) {
2682 rule->cookie_str = malloc(rule->cookie_len + 10);
2683 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2684 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2685 rule->cookie_len += 9;
2686 } else {
2687 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002688 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002689 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2690 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002691 }
2692 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 rule->type = type;
2694 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002695 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002696 LIST_INIT(&rule->list);
2697 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002698 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2699 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002700 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002701 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002702 struct switching_rule *rule;
2703
Willy Tarreaub099aca2008-10-12 17:26:37 +02002704 if (curproxy == &defproxy) {
2705 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002708 }
2709
Willy Tarreau55ea7572007-06-17 19:56:27 +02002710 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002711 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712
2713 if (*(args[1]) == 0) {
2714 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 }
2718
Willy Tarreauef6494c2010-01-28 17:12:36 +01002719 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002720 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2721 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002724 }
2725
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002726 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2727 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2728 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002731 }
2732
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002733 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002734
Willy Tarreau55ea7572007-06-17 19:56:27 +02002735 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2736 rule->cond = cond;
2737 rule->be.name = strdup(args[1]);
2738 LIST_INIT(&rule->list);
2739 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2740 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002741 else if (strcmp(args[0], "use-server") == 0) {
2742 struct server_rule *rule;
2743
2744 if (curproxy == &defproxy) {
2745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749
2750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2751 err_code |= ERR_WARN;
2752
2753 if (*(args[1]) == 0) {
2754 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
2758
2759 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2760 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2761 file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002766 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2767 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2768 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
2773 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2774
2775 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2776 rule->cond = cond;
2777 rule->srv.name = strdup(args[1]);
2778 LIST_INIT(&rule->list);
2779 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2780 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2781 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002782 else if ((!strcmp(args[0], "force-persist")) ||
2783 (!strcmp(args[0], "ignore-persist"))) {
2784 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002785
2786 if (curproxy == &defproxy) {
2787 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790 }
2791
2792 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2793 err_code |= ERR_WARN;
2794
Willy Tarreauef6494c2010-01-28 17:12:36 +01002795 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002796 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2797 file, linenum, args[0]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002802 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2803 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2804 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
2808
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002809 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002810
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002811 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002812 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002813 if (!strcmp(args[0], "force-persist")) {
2814 rule->type = PERSIST_TYPE_FORCE;
2815 } else {
2816 rule->type = PERSIST_TYPE_IGNORE;
2817 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002818 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002819 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002820 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002821 else if (!strcmp(args[0], "stick-table")) {
2822 int myidx = 1;
2823
Emeric Brun32da3c42010-09-23 18:39:19 +02002824 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002825 curproxy->table.type = (unsigned int)-1;
2826 while (*args[myidx]) {
2827 const char *err;
2828
2829 if (strcmp(args[myidx], "size") == 0) {
2830 myidx++;
2831 if (!*(args[myidx])) {
2832 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2833 file, linenum, args[myidx-1]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2838 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2839 file, linenum, *err, args[myidx-1]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002843 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002845 else if (strcmp(args[myidx], "peers") == 0) {
2846 myidx++;
2847 if (!*(args[myidx])) {
2848 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2849 file, linenum, args[myidx-1]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853 curproxy->table.peers.name = strdup(args[myidx++]);
2854 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002855 else if (strcmp(args[myidx], "expire") == 0) {
2856 myidx++;
2857 if (!*(args[myidx])) {
2858 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2859 file, linenum, args[myidx-1]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2864 if (err) {
2865 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2866 file, linenum, *err, args[myidx-1]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002871 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002872 }
2873 else if (strcmp(args[myidx], "nopurge") == 0) {
2874 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002875 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002876 }
2877 else if (strcmp(args[myidx], "type") == 0) {
2878 myidx++;
2879 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2880 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2881 file, linenum, args[myidx]);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002885 /* myidx already points to next arg */
2886 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002887 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002888 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002889 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002890
2891 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002892 nw = args[myidx];
2893 while (*nw) {
2894 /* the "store" keyword supports a comma-separated list */
2895 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002896 sa = NULL; /* store arg */
2897 while (*nw && *nw != ',') {
2898 if (*nw == '(') {
2899 *nw = 0;
2900 sa = ++nw;
2901 while (*nw != ')') {
2902 if (!*nw) {
2903 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2904 file, linenum, args[0], cw);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908 nw++;
2909 }
2910 *nw = '\0';
2911 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002912 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002913 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002914 if (*nw)
2915 *nw++ = '\0';
2916 type = stktable_get_data_type(cw);
2917 if (type < 0) {
2918 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2919 file, linenum, args[0], cw);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
Willy Tarreauac782882010-06-20 10:41:54 +02002923
2924 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2925 switch (err) {
2926 case PE_NONE: break;
2927 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002928 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2929 file, linenum, args[0], cw);
2930 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002931 break;
2932
2933 case PE_ARG_MISSING:
2934 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2935 file, linenum, args[0], cw);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938
2939 case PE_ARG_NOT_USED:
2940 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2941 file, linenum, args[0], cw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944
2945 default:
2946 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2947 file, linenum, args[0], cw);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002950 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002951 }
2952 myidx++;
2953 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002954 else {
2955 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2956 file, linenum, args[myidx]);
2957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002959 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 }
2961
2962 if (!curproxy->table.size) {
2963 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2964 file, linenum);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968
2969 if (curproxy->table.type == (unsigned int)-1) {
2970 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2971 file, linenum);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975 }
2976 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002977 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002978 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 int myidx = 0;
2980 const char *name = NULL;
2981 int flags;
2982
2983 if (curproxy == &defproxy) {
2984 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
2989 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2990 err_code |= ERR_WARN;
2991 goto out;
2992 }
2993
2994 myidx++;
2995 if ((strcmp(args[myidx], "store") == 0) ||
2996 (strcmp(args[myidx], "store-request") == 0)) {
2997 myidx++;
2998 flags = STK_IS_STORE;
2999 }
3000 else if (strcmp(args[myidx], "store-response") == 0) {
3001 myidx++;
3002 flags = STK_IS_STORE | STK_ON_RSP;
3003 }
3004 else if (strcmp(args[myidx], "match") == 0) {
3005 myidx++;
3006 flags = STK_IS_MATCH;
3007 }
3008 else if (strcmp(args[myidx], "on") == 0) {
3009 myidx++;
3010 flags = STK_IS_MATCH | STK_IS_STORE;
3011 }
3012 else {
3013 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
3018 if (*(args[myidx]) == 0) {
3019 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
David du Colombier7af46052012-05-16 14:16:48 +02003024 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003025 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003026 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
3031 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003032 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3034 file, linenum, args[0], expr->fetch->kw);
3035 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003036 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003037 goto out;
3038 }
3039 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003040 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3042 file, linenum, args[0], expr->fetch->kw);
3043 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003044 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 goto out;
3046 }
3047 }
3048
3049 if (strcmp(args[myidx], "table") == 0) {
3050 myidx++;
3051 name = args[myidx++];
3052 }
3053
Willy Tarreauef6494c2010-01-28 17:12:36 +01003054 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003055 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3056 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3057 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003059 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 goto out;
3061 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003063 else if (*(args[myidx])) {
3064 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3065 file, linenum, args[0], args[myidx]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003067 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003068 goto out;
3069 }
Emeric Brun97679e72010-09-23 17:56:44 +02003070 if (flags & STK_ON_RSP)
3071 err_code |= warnif_cond_requires_req(cond, file, linenum);
3072 else
3073 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003074
Emeric Brunb982a3d2010-01-04 15:45:53 +01003075 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3076 rule->cond = cond;
3077 rule->expr = expr;
3078 rule->flags = flags;
3079 rule->table.name = name ? strdup(name) : NULL;
3080 LIST_INIT(&rule->list);
3081 if (flags & STK_ON_RSP)
3082 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3083 else
3084 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003087 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003089
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3091 curproxy->uri_auth = NULL; /* we must detach from the default config */
3092
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003093 if (!*args[1]) {
3094 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003095 } else if (!strcmp(args[1], "admin")) {
3096 struct stats_admin_rule *rule;
3097
3098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
3104 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3105 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
3108 }
3109
3110 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3111 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3112 file, linenum, args[0], args[1]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003116 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3117 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3118 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
3122
3123 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3124
3125 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3126 rule->cond = cond;
3127 LIST_INIT(&rule->list);
3128 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 } else if (!strcmp(args[1], "uri")) {
3130 if (*(args[2]) == 0) {
3131 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_ABORT;
3137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 }
3139 } else if (!strcmp(args[1], "realm")) {
3140 if (*(args[2]) == 0) {
3141 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3145 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_ABORT;
3147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003149 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003150 unsigned interval;
3151
3152 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3153 if (err) {
3154 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3155 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003158 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3159 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_ABORT;
3161 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003162 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003163 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003164 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003165
3166 if (curproxy == &defproxy) {
3167 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171
3172 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3173 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3174 err_code |= ERR_ALERT | ERR_ABORT;
3175 goto out;
3176 }
3177
Willy Tarreauff011f22011-01-06 17:51:27 +01003178 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3179 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003180 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3181 file, linenum, args[0]);
3182 err_code |= ERR_WARN;
3183 }
3184
Willy Tarreauff011f22011-01-06 17:51:27 +01003185 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003186
Willy Tarreauff011f22011-01-06 17:51:27 +01003187 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
3190 }
3191
Willy Tarreauff011f22011-01-06 17:51:27 +01003192 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3193 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003194
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 } else if (!strcmp(args[1], "auth")) {
3196 if (*(args[2]) == 0) {
3197 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3201 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_ABORT;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 }
3205 } else if (!strcmp(args[1], "scope")) {
3206 if (*(args[2]) == 0) {
3207 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_ABORT;
3213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
3215 } else if (!strcmp(args[1], "enable")) {
3216 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_ABORT;
3219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003221 } else if (!strcmp(args[1], "hide-version")) {
3222 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_ALERT | ERR_ABORT;
3225 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003226 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003227 } else if (!strcmp(args[1], "show-legends")) {
3228 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3229 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3230 err_code |= ERR_ALERT | ERR_ABORT;
3231 goto out;
3232 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003233 } else if (!strcmp(args[1], "show-node")) {
3234
3235 if (*args[2]) {
3236 int i;
3237 char c;
3238
3239 for (i=0; args[2][i]; i++) {
3240 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003241 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3242 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003243 break;
3244 }
3245
3246 if (!i || args[2][i]) {
3247 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3248 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3249 file, linenum, args[0], args[1]);
3250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
3252 }
3253 }
3254
3255 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3256 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3257 err_code |= ERR_ALERT | ERR_ABORT;
3258 goto out;
3259 }
3260 } else if (!strcmp(args[1], "show-desc")) {
3261 char *desc = NULL;
3262
3263 if (*args[2]) {
3264 int i, len=0;
3265 char *d;
3266
3267 for(i=2; *args[i]; i++)
3268 len += strlen(args[i])+1;
3269
3270 desc = d = (char *)calloc(1, len);
3271
3272 d += sprintf(d, "%s", args[2]);
3273 for(i=3; *args[i]; i++)
3274 d += sprintf(d, " %s", args[i]);
3275 }
3276
3277 if (!*args[2] && !global.desc)
3278 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3279 file, linenum, args[1]);
3280 else {
3281 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3282 free(desc);
3283 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3284 err_code |= ERR_ALERT | ERR_ABORT;
3285 goto out;
3286 }
3287 free(desc);
3288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003290stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003291 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 +01003292 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 }
3296 }
3297 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003298 int optnum;
3299
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003300 if (*(args[1]) == '\0') {
3301 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003306
3307 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3308 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003309 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3310 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3311 file, linenum, cfg_opts[optnum].name);
3312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
Willy Tarreau93893792009-07-23 13:19:11 +02003315 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3316 err_code |= ERR_WARN;
3317 goto out;
3318 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003319
Willy Tarreau3842f002009-06-14 11:39:52 +02003320 curproxy->no_options &= ~cfg_opts[optnum].val;
3321 curproxy->options &= ~cfg_opts[optnum].val;
3322
3323 switch (kwm) {
3324 case KWM_STD:
3325 curproxy->options |= cfg_opts[optnum].val;
3326 break;
3327 case KWM_NO:
3328 curproxy->no_options |= cfg_opts[optnum].val;
3329 break;
3330 case KWM_DEF: /* already cleared */
3331 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003332 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003333
Willy Tarreau93893792009-07-23 13:19:11 +02003334 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003335 }
3336 }
3337
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003338 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3339 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003340 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3341 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3342 file, linenum, cfg_opts2[optnum].name);
3343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
Willy Tarreau93893792009-07-23 13:19:11 +02003346 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3347 err_code |= ERR_WARN;
3348 goto out;
3349 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003350
Willy Tarreau3842f002009-06-14 11:39:52 +02003351 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3352 curproxy->options2 &= ~cfg_opts2[optnum].val;
3353
3354 switch (kwm) {
3355 case KWM_STD:
3356 curproxy->options2 |= cfg_opts2[optnum].val;
3357 break;
3358 case KWM_NO:
3359 curproxy->no_options2 |= cfg_opts2[optnum].val;
3360 break;
3361 case KWM_DEF: /* already cleared */
3362 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003363 }
Willy Tarreau93893792009-07-23 13:19:11 +02003364 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003365 }
3366 }
3367
Willy Tarreau3842f002009-06-14 11:39:52 +02003368 if (kwm != KWM_STD) {
3369 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003370 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003373 }
3374
Emeric Brun3a058f32009-06-30 18:26:00 +02003375 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003376 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003378 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003379 if (*(args[2]) != '\0') {
3380 if (!strcmp(args[2], "clf")) {
3381 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003382 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003383 } else {
3384 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003387 }
3388 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003389 if (curproxy->logformat_string != default_http_log_format &&
3390 curproxy->logformat_string != default_tcp_log_format &&
3391 curproxy->logformat_string != clf_http_log_format)
3392 free(curproxy->logformat_string);
3393 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003394 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003395 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003397 if (curproxy->logformat_string != default_http_log_format &&
3398 curproxy->logformat_string != default_tcp_log_format &&
3399 curproxy->logformat_string != clf_http_log_format)
3400 free(curproxy->logformat_string);
3401 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 else if (!strcmp(args[1], "tcpka")) {
3404 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003405 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003407
3408 if (curproxy->cap & PR_CAP_FE)
3409 curproxy->options |= PR_O_TCP_CLI_KA;
3410 if (curproxy->cap & PR_CAP_BE)
3411 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_WARN;
3416
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
3421 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 if (!*args[2]) { /* no argument */
3423 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3424 curproxy->check_len = strlen(DEF_CHECK_REQ);
3425 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003426 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 curproxy->check_req = (char *)malloc(reqlen);
3428 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003429 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003431 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 if (*args[4])
3433 reqlen += strlen(args[4]);
3434 else
3435 reqlen += strlen("HTTP/1.0");
3436
3437 curproxy->check_req = (char *)malloc(reqlen);
3438 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003439 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003441 }
3442 else if (!strcmp(args[1], "ssl-hello-chk")) {
3443 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003446
Willy Tarreaua534fea2008-08-03 12:19:50 +02003447 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003448 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003449 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003450 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 }
Willy Tarreau23677902007-05-08 23:50:35 +02003452 else if (!strcmp(args[1], "smtpchk")) {
3453 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003454 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003455 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003456 curproxy->options2 &= ~PR_O2_CHK_ANY;
3457 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003458
3459 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3460 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3461 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3462 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3463 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3464 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3465 curproxy->check_req = (char *)malloc(reqlen);
3466 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3467 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3468 } else {
3469 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3470 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3471 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3472 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3473 }
3474 }
3475 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003476 else if (!strcmp(args[1], "pgsql-check")) {
3477 /* use PostgreSQL request to check servers' health */
3478 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3479 err_code |= ERR_WARN;
3480
3481 free(curproxy->check_req);
3482 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003483 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003484 curproxy->options2 |= PR_O2_PGSQL_CHK;
3485
3486 if (*(args[2])) {
3487 int cur_arg = 2;
3488
3489 while (*(args[cur_arg])) {
3490 if (strcmp(args[cur_arg], "user") == 0) {
3491 char * packet;
3492 uint32_t packet_len;
3493 uint32_t pv;
3494
3495 /* suboption header - needs additional argument for it */
3496 if (*(args[cur_arg+1]) == 0) {
3497 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3498 file, linenum, args[0], args[1], args[cur_arg]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502
3503 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3504 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3505 pv = htonl(0x30000); /* protocol version 3.0 */
3506
3507 packet = (char*) calloc(1, packet_len);
3508
3509 memcpy(packet + 4, &pv, 4);
3510
3511 /* copy "user" */
3512 memcpy(packet + 8, "user", 4);
3513
3514 /* copy username */
3515 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3516
3517 free(curproxy->check_req);
3518 curproxy->check_req = packet;
3519 curproxy->check_len = packet_len;
3520
3521 packet_len = htonl(packet_len);
3522 memcpy(packet, &packet_len, 4);
3523 cur_arg += 2;
3524 } else {
3525 /* unknown suboption - catchall */
3526 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3527 file, linenum, args[0], args[1]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531 } /* end while loop */
3532 }
3533 }
3534
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003535 else if (!strcmp(args[1], "redis-check")) {
3536 /* use REDIS PING request to check servers' health */
3537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3538 err_code |= ERR_WARN;
3539
3540 free(curproxy->check_req);
3541 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003542 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003543 curproxy->options2 |= PR_O2_REDIS_CHK;
3544
3545 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3546 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3547 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3548 }
3549
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003550 else if (!strcmp(args[1], "mysql-check")) {
3551 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003552 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3553 err_code |= ERR_WARN;
3554
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003555 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003556 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003557 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003558 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003559
3560 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3561 * const char mysql40_client_auth_pkt[] = {
3562 * "\x0e\x00\x00" // packet length
3563 * "\x01" // packet number
3564 * "\x00\x00" // client capabilities
3565 * "\x00\x00\x01" // max packet
3566 * "haproxy\x00" // username (null terminated string)
3567 * "\x00" // filler (always 0x00)
3568 * "\x01\x00\x00" // packet length
3569 * "\x00" // packet number
3570 * "\x01" // COM_QUIT command
3571 * };
3572 */
3573
3574 if (*(args[2])) {
3575 int cur_arg = 2;
3576
3577 while (*(args[cur_arg])) {
3578 if (strcmp(args[cur_arg], "user") == 0) {
3579 char *mysqluser;
3580 int packetlen, reqlen, userlen;
3581
3582 /* suboption header - needs additional argument for it */
3583 if (*(args[cur_arg+1]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3585 file, linenum, args[0], args[1], args[cur_arg]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589 mysqluser = args[cur_arg + 1];
3590 userlen = strlen(mysqluser);
3591 packetlen = userlen + 7;
3592 reqlen = packetlen + 9;
3593
3594 free(curproxy->check_req);
3595 curproxy->check_req = (char *)calloc(1, reqlen);
3596 curproxy->check_len = reqlen;
3597
3598 snprintf(curproxy->check_req, 4, "%c%c%c",
3599 ((unsigned char) packetlen & 0xff),
3600 ((unsigned char) (packetlen >> 8) & 0xff),
3601 ((unsigned char) (packetlen >> 16) & 0xff));
3602
3603 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003604 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003605 curproxy->check_req[8] = 1;
3606 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3607 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3608 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3609 cur_arg += 2;
3610 } else {
3611 /* unknown suboption - catchall */
3612 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3613 file, linenum, args[0], args[1]);
3614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
3616 }
3617 } /* end while loop */
3618 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003619 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003620 else if (!strcmp(args[1], "ldap-check")) {
3621 /* use LDAP request to check servers' health */
3622 free(curproxy->check_req);
3623 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003624 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003625 curproxy->options2 |= PR_O2_LDAP_CHK;
3626
3627 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3628 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3629 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3630 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003631 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003632 int cur_arg;
3633
3634 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3635 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003636 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003637
Willy Tarreau87cf5142011-08-19 22:57:24 +02003638 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003639
3640 free(curproxy->fwdfor_hdr_name);
3641 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3642 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3643
3644 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3645 cur_arg = 2;
3646 while (*(args[cur_arg])) {
3647 if (!strcmp(args[cur_arg], "except")) {
3648 /* suboption except - needs additional argument for it */
3649 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3650 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3651 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003654 }
3655 /* flush useless bits */
3656 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003657 cur_arg += 2;
3658 } else if (!strcmp(args[cur_arg], "header")) {
3659 /* suboption header - needs additional argument for it */
3660 if (*(args[cur_arg+1]) == 0) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3662 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 }
3666 free(curproxy->fwdfor_hdr_name);
3667 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3668 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3669 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003670 } else if (!strcmp(args[cur_arg], "if-none")) {
3671 curproxy->options &= ~PR_O_FF_ALWAYS;
3672 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003673 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003674 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003675 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003676 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003679 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003680 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003681 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003682 else if (!strcmp(args[1], "originalto")) {
3683 int cur_arg;
3684
3685 /* insert x-original-to field, but not for the IP address listed as an except.
3686 * set default options (ie: bitfield, header name, etc)
3687 */
3688
3689 curproxy->options |= PR_O_ORGTO;
3690
3691 free(curproxy->orgto_hdr_name);
3692 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3693 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3694
Willy Tarreau87cf5142011-08-19 22:57:24 +02003695 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003696 cur_arg = 2;
3697 while (*(args[cur_arg])) {
3698 if (!strcmp(args[cur_arg], "except")) {
3699 /* suboption except - needs additional argument for it */
3700 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3702 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003705 }
3706 /* flush useless bits */
3707 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3708 cur_arg += 2;
3709 } else if (!strcmp(args[cur_arg], "header")) {
3710 /* suboption header - needs additional argument for it */
3711 if (*(args[cur_arg+1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3713 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003716 }
3717 free(curproxy->orgto_hdr_name);
3718 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3719 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3720 cur_arg += 2;
3721 } else {
3722 /* unknown suboption - catchall */
3723 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3724 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003727 }
3728 } /* end while loop */
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else {
3731 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 }
Willy Tarreau93893792009-07-23 13:19:11 +02003735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003736 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003737 else if (!strcmp(args[0], "default_backend")) {
3738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003740
3741 if (*(args[1]) == 0) {
3742 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003745 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003746 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003747 curproxy->defbe.name = strdup(args[1]);
3748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003749 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003752
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003753 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3754 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 /* enable reconnections to dispatch */
3757 curproxy->options |= PR_O_REDISP;
3758 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003759 else if (!strcmp(args[0], "http-check")) {
3760 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003762
3763 if (strcmp(args[1], "disable-on-404") == 0) {
3764 /* enable a graceful server shutdown on an HTTP 404 response */
3765 curproxy->options |= PR_O_DISABLE404;
3766 }
Willy Tarreauef781042010-01-27 11:53:01 +01003767 else if (strcmp(args[1], "send-state") == 0) {
3768 /* enable emission of the apparent state of a server in HTTP checks */
3769 curproxy->options2 |= PR_O2_CHK_SNDST;
3770 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003771 else if (strcmp(args[1], "expect") == 0) {
3772 const char *ptr_arg;
3773 int cur_arg;
3774
3775 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3776 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
3779 }
3780
3781 cur_arg = 2;
3782 /* consider exclamation marks, sole or at the beginning of a word */
3783 while (*(ptr_arg = args[cur_arg])) {
3784 while (*ptr_arg == '!') {
3785 curproxy->options2 ^= PR_O2_EXP_INV;
3786 ptr_arg++;
3787 }
3788 if (*ptr_arg)
3789 break;
3790 cur_arg++;
3791 }
3792 /* now ptr_arg points to the beginning of a word past any possible
3793 * exclamation mark, and cur_arg is the argument which holds this word.
3794 */
3795 if (strcmp(ptr_arg, "status") == 0) {
3796 if (!*(args[cur_arg + 1])) {
3797 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3798 file, linenum, args[0], args[1], ptr_arg);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003803 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003804 curproxy->expect_str = strdup(args[cur_arg + 1]);
3805 }
3806 else if (strcmp(ptr_arg, "string") == 0) {
3807 if (!*(args[cur_arg + 1])) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3809 file, linenum, args[0], args[1], ptr_arg);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003814 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003815 curproxy->expect_str = strdup(args[cur_arg + 1]);
3816 }
3817 else if (strcmp(ptr_arg, "rstatus") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
3826 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3827 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003828 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3829 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3830 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3831 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 }
3836 else if (strcmp(ptr_arg, "rstring") == 0) {
3837 if (!*(args[cur_arg + 1])) {
3838 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3839 file, linenum, args[0], args[1], ptr_arg);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003844 free(curproxy->expect_str);
3845 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3846 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003847 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3848 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3849 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3850 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854 }
3855 else {
3856 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3857 file, linenum, args[0], args[1], ptr_arg);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003862 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003863 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 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003866 }
3867 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003868 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003869 if (curproxy == &defproxy) {
3870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003873 }
3874
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003877
3878 if (strcmp(args[1], "fail") == 0) {
3879 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003880 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3882 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003885 }
3886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3888 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3889 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003892 }
3893 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3894 }
3895 else {
3896 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003899 }
3900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901#ifdef TPROXY
3902 else if (!strcmp(args[0], "transparent")) {
3903 /* enable transparent proxy connections */
3904 curproxy->options |= PR_O_TRANSP;
3905 }
3906#endif
3907 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003908 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003910
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 if (*(args[1]) == 0) {
3912 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 }
3916 curproxy->maxconn = atol(args[1]);
3917 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003918 else if (!strcmp(args[0], "backlog")) { /* backlog */
3919 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003921
3922 if (*(args[1]) == 0) {
3923 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003926 }
3927 curproxy->backlog = atol(args[1]);
3928 }
Willy Tarreau86034312006-12-29 00:10:33 +01003929 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003932
Willy Tarreau86034312006-12-29 00:10:33 +01003933 if (*(args[1]) == 0) {
3934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003937 }
3938 curproxy->fullconn = atol(args[1]);
3939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3941 if (*(args[1]) == 0) {
3942 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003946 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3947 if (err) {
3948 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3949 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003952 }
3953 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
3955 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003956 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 if (curproxy == &defproxy) {
3958 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003962 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003964
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 if (strchr(args[1], ':') == NULL) {
3966 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003970 sk = str2sa(args[1]);
3971 if (!sk) {
3972 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
3975 }
3976 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003977 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 }
3979 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003982
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003983 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3984 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003989 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3990 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3991 err_code |= ERR_WARN;
3992
3993 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3994 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3995 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3996 }
3997 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3998 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3999 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4000 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004001 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4002 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4003 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4004 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004005 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004006 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
4009 }
4010 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004011 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004013 char *rport, *raddr;
4014 short realport = 0;
4015 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004022 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024
4025 if (!*args[2]) {
4026 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004031
4032 err = invalid_char(args[1]);
4033 if (err) {
4034 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4035 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004038 }
4039
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004040 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004041 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004042
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004043 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4044 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4045 err_code |= ERR_ALERT | ERR_ABORT;
4046 goto out;
4047 }
4048
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004049 /* the servers are linked backwards first */
4050 newsrv->next = curproxy->srv;
4051 curproxy->srv = newsrv;
4052 newsrv->proxy = curproxy;
4053 newsrv->conf.file = file;
4054 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004055
Simon Hormanaf514952011-06-21 14:34:57 +09004056 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 LIST_INIT(&newsrv->pendconns);
4058 do_check = 0;
4059 newsrv->state = SRV_RUNNING; /* early server setup */
4060 newsrv->last_change = now.tv_sec;
4061 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004064 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004065 * - IP: => port=+0, relative
4066 * - IP:N => port=N, absolute
4067 * - IP:+N => port=+N, relative
4068 * - IP:-N => port=-N, relative
4069 */
4070 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004071 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004072 if (rport) {
4073 *rport++ = 0;
4074 realport = atol(rport);
4075 if (!isdigit((unsigned char)*rport))
4076 newsrv->state |= SRV_MAPPORTS;
4077 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079
Willy Tarreaufab5a432011-03-04 15:31:53 +01004080 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004081 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004082 if (!sk) {
4083 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
4087 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004088 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004089 newsrv->sock = &sock_raw;
4090 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004091
4092 if (!sk) {
4093 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4094 file, linenum, newsrv->addr.ss_family, args[2]);
4095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
4097 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004098 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004099
4100 newsrv->check_port = curproxy->defsrv.check_port;
4101 newsrv->inter = curproxy->defsrv.inter;
4102 newsrv->fastinter = curproxy->defsrv.fastinter;
4103 newsrv->downinter = curproxy->defsrv.downinter;
4104 newsrv->rise = curproxy->defsrv.rise;
4105 newsrv->fall = curproxy->defsrv.fall;
4106 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4107 newsrv->minconn = curproxy->defsrv.minconn;
4108 newsrv->maxconn = curproxy->defsrv.maxconn;
4109 newsrv->slowstart = curproxy->defsrv.slowstart;
4110 newsrv->onerror = curproxy->defsrv.onerror;
4111 newsrv->consecutive_errors_limit
4112 = curproxy->defsrv.consecutive_errors_limit;
4113 newsrv->uweight = newsrv->iweight
4114 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 newsrv->curfd = -1; /* no health-check in progress */
4117 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004118
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004119 cur_arg = 3;
4120 } else {
4121 newsrv = &curproxy->defsrv;
4122 cur_arg = 1;
4123 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004124
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004126 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004127 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004128
4129 if (!*args[cur_arg + 1]) {
4130 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4131 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004134 }
4135
4136 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004137 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004138
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004139 if (newsrv->puid <= 0) {
4140 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004141 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004144 }
4145
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004146 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4147 if (node) {
4148 struct server *target = container_of(node, struct server, conf.id);
4149 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4150 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004155 cur_arg += 2;
4156 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 newsrv->cookie = strdup(args[cur_arg + 1]);
4159 newsrv->cklen = strlen(args[cur_arg + 1]);
4160 cur_arg += 2;
4161 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004162 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004163 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4164 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4165 cur_arg += 2;
4166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004168 if (!*args[cur_arg + 1]) {
4169 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4170 file, linenum, args[cur_arg]);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004176 if (newsrv->rise <= 0) {
4177 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4178 file, linenum, args[cur_arg]);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
4182
Willy Tarreau96839092010-03-29 10:02:24 +02004183 if (newsrv->health)
4184 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 cur_arg += 2;
4186 }
4187 else if (!strcmp(args[cur_arg], "fall")) {
4188 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004189
4190 if (!*args[cur_arg + 1]) {
4191 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4192 file, linenum, args[cur_arg]);
4193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
4195 }
4196
4197 if (newsrv->fall <= 0) {
4198 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4199 file, linenum, args[cur_arg]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
4203
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 cur_arg += 2;
4205 }
4206 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004207 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4208 if (err) {
4209 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4210 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004213 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004214 if (val <= 0) {
4215 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4216 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004219 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004220 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 cur_arg += 2;
4222 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004223 else if (!strcmp(args[cur_arg], "fastinter")) {
4224 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4225 if (err) {
4226 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4227 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004230 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004231 if (val <= 0) {
4232 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4233 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004236 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004237 newsrv->fastinter = val;
4238 cur_arg += 2;
4239 }
4240 else if (!strcmp(args[cur_arg], "downinter")) {
4241 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4242 if (err) {
4243 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4244 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004247 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004248 if (val <= 0) {
4249 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4250 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004253 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004254 newsrv->downinter = val;
4255 cur_arg += 2;
4256 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004257 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004258 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004259 if (!sk) {
4260 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
4264 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004265 cur_arg += 2;
4266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 else if (!strcmp(args[cur_arg], "port")) {
4268 newsrv->check_port = atol(args[cur_arg + 1]);
4269 cur_arg += 2;
4270 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004271 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 newsrv->state |= SRV_BACKUP;
4273 cur_arg ++;
4274 }
Simon Hormanfa461682011-06-25 09:39:49 +09004275 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4276 newsrv->state |= SRV_NON_STICK;
4277 cur_arg ++;
4278 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004279 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4280 newsrv->state |= SRV_SEND_PROXY;
4281 cur_arg ++;
4282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 else if (!strcmp(args[cur_arg], "weight")) {
4284 int w;
4285 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004286 if (w < 0 || w > 256) {
4287 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004292 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 cur_arg += 2;
4294 }
4295 else if (!strcmp(args[cur_arg], "minconn")) {
4296 newsrv->minconn = atol(args[cur_arg + 1]);
4297 cur_arg += 2;
4298 }
4299 else if (!strcmp(args[cur_arg], "maxconn")) {
4300 newsrv->maxconn = atol(args[cur_arg + 1]);
4301 cur_arg += 2;
4302 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004303 else if (!strcmp(args[cur_arg], "maxqueue")) {
4304 newsrv->maxqueue = atol(args[cur_arg + 1]);
4305 cur_arg += 2;
4306 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004307 else if (!strcmp(args[cur_arg], "slowstart")) {
4308 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004309 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004310 if (err) {
4311 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4312 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004315 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004316 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004317 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4318 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004321 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004322 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004323 cur_arg += 2;
4324 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004325 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004326
4327 if (!*args[cur_arg + 1]) {
4328 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4329 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004332 }
4333
4334 newsrv->trackit = strdup(args[cur_arg + 1]);
4335
4336 cur_arg += 2;
4337 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004338 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 global.maxsock++;
4340 do_check = 1;
4341 cur_arg += 1;
4342 }
Willy Tarreau96839092010-03-29 10:02:24 +02004343 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4344 newsrv->state |= SRV_MAINTAIN;
4345 newsrv->state &= ~SRV_RUNNING;
4346 newsrv->health = 0;
4347 cur_arg += 1;
4348 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004349 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004350 if (!strcmp(args[cur_arg + 1], "none"))
4351 newsrv->observe = HANA_OBS_NONE;
4352 else if (!strcmp(args[cur_arg + 1], "layer4"))
4353 newsrv->observe = HANA_OBS_LAYER4;
4354 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4355 if (curproxy->mode != PR_MODE_HTTP) {
4356 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4357 file, linenum, args[cur_arg + 1]);
4358 err_code |= ERR_ALERT;
4359 }
4360 newsrv->observe = HANA_OBS_LAYER7;
4361 }
4362 else {
4363 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004364 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004365 file, linenum, args[cur_arg], args[cur_arg + 1]);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
4369
4370 cur_arg += 2;
4371 }
4372 else if (!strcmp(args[cur_arg], "on-error")) {
4373 if (!strcmp(args[cur_arg + 1], "fastinter"))
4374 newsrv->onerror = HANA_ONERR_FASTINTER;
4375 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4376 newsrv->onerror = HANA_ONERR_FAILCHK;
4377 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4378 newsrv->onerror = HANA_ONERR_SUDDTH;
4379 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4380 newsrv->onerror = HANA_ONERR_MARKDWN;
4381 else {
4382 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004383 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004384 file, linenum, args[cur_arg], args[cur_arg + 1]);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388
4389 cur_arg += 2;
4390 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004391 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4392 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4393 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4394 else {
4395 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4396 file, linenum, args[cur_arg], args[cur_arg + 1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400
4401 cur_arg += 2;
4402 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004403 else if (!strcmp(args[cur_arg], "error-limit")) {
4404 if (!*args[cur_arg + 1]) {
4405 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4406 file, linenum, args[cur_arg]);
4407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
4409 }
4410
4411 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4412
4413 if (newsrv->consecutive_errors_limit <= 0) {
4414 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4415 file, linenum, args[cur_arg]);
4416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
4418 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004419 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004420 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004421 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004422 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004423 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004424
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004426#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004427 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004428 file, linenum, "source", "usesrc");
4429#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004430 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004432#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 }
4436 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004437 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4438 if (!sk) {
4439 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
4442 }
4443 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004444
4445 if (port_low != port_high) {
4446 int i;
4447 if (port_low <= 0 || port_low > 65535 ||
4448 port_high <= 0 || port_high > 65535 ||
4449 port_low > port_high) {
4450 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4451 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004454 }
4455 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4456 for (i = 0; i < newsrv->sport_range->size; i++)
4457 newsrv->sport_range->ports[i] = port_low + i;
4458 }
4459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004461 while (*(args[cur_arg])) {
4462 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004463#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4464#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4466 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4467 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004470 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004471#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004472 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004473 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004474 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004477 }
4478 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004479 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004480 newsrv->state |= SRV_TPROXY_CLI;
4481 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004482 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004484 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4485 char *name, *end;
4486
4487 name = args[cur_arg+1] + 7;
4488 while (isspace(*name))
4489 name++;
4490
4491 end = name;
4492 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4493 end++;
4494
4495 newsrv->state &= ~SRV_TPROXY_MASK;
4496 newsrv->state |= SRV_TPROXY_DYN;
4497 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4498 newsrv->bind_hdr_len = end - name;
4499 memcpy(newsrv->bind_hdr_name, name, end - name);
4500 newsrv->bind_hdr_name[end-name] = '\0';
4501 newsrv->bind_hdr_occ = -1;
4502
4503 /* now look for an occurrence number */
4504 while (isspace(*end))
4505 end++;
4506 if (*end == ',') {
4507 end++;
4508 name = end;
4509 if (*end == '-')
4510 end++;
4511 while (isdigit(*end))
4512 end++;
4513 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4514 }
4515
4516 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4517 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4518 " occurrences values smaller than %d.\n",
4519 file, linenum, MAX_HDR_HISTORY);
4520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
4522 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004524 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004525 if (!sk) {
4526 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
4529 }
4530 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004531 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004532 }
4533 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004534#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004535 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004536#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 cur_arg += 2;
4538 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004539#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004540 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004541 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004544#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4545 } /* "usesrc" */
4546
4547 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4548#ifdef SO_BINDTODEVICE
4549 if (!*args[cur_arg + 1]) {
4550 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004554 }
4555 if (newsrv->iface_name)
4556 free(newsrv->iface_name);
4557
4558 newsrv->iface_name = strdup(args[cur_arg + 1]);
4559 newsrv->iface_len = strlen(newsrv->iface_name);
4560 global.last_checks |= LSTCHK_NETADM;
4561#else
4562 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4563 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004566#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004567 cur_arg += 2;
4568 continue;
4569 }
4570 /* this keyword in not an option of "source" */
4571 break;
4572 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004574 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004575 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4576 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004581 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004582 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 +01004583 file, linenum, newsrv->id);
4584 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004585 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 +01004586 file, linenum);
4587
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
4591 }
4592
4593 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004594 if (newsrv->trackit) {
4595 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4596 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004599 }
4600
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004601 /* try to get the port from check_addr if check_port not set */
4602 if (!newsrv->check_port)
4603 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004604
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4606 newsrv->check_port = realport; /* by default */
4607 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004608 /* not yet valid, because no port was set on
4609 * the server either. We'll check if we have
4610 * a known port on the first listener.
4611 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004612 struct listener *l = curproxy->listen;
4613 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4614 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004615 }
4616 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4618 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004622
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004623 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004624 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004625 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4626 err_code |= ERR_ALERT | ERR_ABORT;
4627 goto out;
4628 }
4629
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004630 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 newsrv->state |= SRV_CHECKED;
4632 }
4633
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004634 if (!defsrv) {
4635 if (newsrv->state & SRV_BACKUP)
4636 curproxy->srv_bck++;
4637 else
4638 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004639
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004640 newsrv->prev_state = newsrv->state;
4641 }
William Lallemanda73203e2012-03-12 12:48:57 +01004642 }
4643
4644 else if (strcmp(args[0], "unique-id-format") == 0) {
4645 if (!*(args[1])) {
4646 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004650 free(curproxy->uniqueid_format_string);
4651 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004652 }
William Lallemanda73203e2012-03-12 12:48:57 +01004653
4654 else if (strcmp(args[0], "unique-id-header") == 0) {
4655 if (!*(args[1])) {
4656 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
4659 }
4660 free(curproxy->header_unique_id);
4661 curproxy->header_unique_id = strdup(args[1]);
4662 }
4663
William Lallemand723b73a2012-02-08 16:37:49 +01004664 else if (strcmp(args[0], "log-format") == 0) {
4665 if (!*(args[1])) {
4666 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004670
4671 if (curproxy->logformat_string != default_http_log_format &&
4672 curproxy->logformat_string != default_tcp_log_format &&
4673 curproxy->logformat_string != clf_http_log_format)
4674 free(curproxy->logformat_string);
4675 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 }
William Lallemand723b73a2012-02-08 16:37:49 +01004677
William Lallemand0f99e342011-10-12 17:50:54 +02004678 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4679 /* delete previous herited or defined syslog servers */
4680 struct logsrv *back;
4681
4682 if (*(args[1]) != 0) {
4683 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
4686 }
4687
William Lallemand723b73a2012-02-08 16:37:49 +01004688 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4689 LIST_DEL(&tmplogsrv->list);
4690 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004691 }
4692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004694 struct logsrv *logsrv;
4695
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004697 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004698 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004699 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004700 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004701 LIST_INIT(&node->list);
4702 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
4705 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004706
4707 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708
William Lallemand0f99e342011-10-12 17:50:54 +02004709 logsrv->facility = get_log_facility(args[2]);
4710 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 }
4716
William Lallemand0f99e342011-10-12 17:50:54 +02004717 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004719 logsrv->level = get_log_level(args[3]);
4720 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724
Willy Tarreaubaaee002006-06-26 02:48:02 +02004725 }
4726 }
4727
William Lallemand0f99e342011-10-12 17:50:54 +02004728 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004729 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004730 logsrv->minlvl = get_log_level(args[4]);
4731 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004732 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004736 }
4737 }
4738
Robert Tsai81ae1952007-12-05 10:47:29 +01004739 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004740 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004741 if (!sk) {
4742 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004743 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
4746 }
William Lallemand0f99e342011-10-12 17:50:54 +02004747 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004748 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004749 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004750 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004751 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
4754 }
William Lallemand0f99e342011-10-12 17:50:54 +02004755 logsrv->addr = *sk;
4756 if (!get_host_port(&logsrv->addr))
4757 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
William Lallemand0f99e342011-10-12 17:50:54 +02004759
4760 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
4762 else {
4763 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4764 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
4768 }
4769 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004770 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004771 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004772
Willy Tarreau977b8e42006-12-29 14:19:17 +01004773 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004774 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004775
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004777 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4778 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004782
4783 /* we must first clear any optional default setting */
4784 curproxy->options &= ~PR_O_TPXY_MASK;
4785 free(curproxy->iface_name);
4786 curproxy->iface_name = NULL;
4787 curproxy->iface_len = 0;
4788
Willy Tarreaud5191e72010-02-09 20:50:45 +01004789 sk = str2sa(args[1]);
4790 if (!sk) {
4791 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
4795 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004797
4798 cur_arg = 2;
4799 while (*(args[cur_arg])) {
4800 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004801#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4802#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4804 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4805 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004808 }
4809#endif
4810 if (!*args[cur_arg + 1]) {
4811 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4812 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004815 }
4816
4817 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004818 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004819 curproxy->options |= PR_O_TPXY_CLI;
4820 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004821 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004822 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004823 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4824 char *name, *end;
4825
4826 name = args[cur_arg+1] + 7;
4827 while (isspace(*name))
4828 name++;
4829
4830 end = name;
4831 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4832 end++;
4833
4834 curproxy->options &= ~PR_O_TPXY_MASK;
4835 curproxy->options |= PR_O_TPXY_DYN;
4836 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4837 curproxy->bind_hdr_len = end - name;
4838 memcpy(curproxy->bind_hdr_name, name, end - name);
4839 curproxy->bind_hdr_name[end-name] = '\0';
4840 curproxy->bind_hdr_occ = -1;
4841
4842 /* now look for an occurrence number */
4843 while (isspace(*end))
4844 end++;
4845 if (*end == ',') {
4846 end++;
4847 name = end;
4848 if (*end == '-')
4849 end++;
4850 while (isdigit(*end))
4851 end++;
4852 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4853 }
4854
4855 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4856 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4857 " occurrences values smaller than %d.\n",
4858 file, linenum, MAX_HDR_HISTORY);
4859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004862 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004863 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004864 if (!sk) {
4865 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004871 }
4872 global.last_checks |= LSTCHK_NETADM;
4873#if !defined(CONFIG_HAP_LINUX_TPROXY)
4874 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004875#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004876#else /* no TPROXY support */
4877 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004878 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004881#endif
4882 cur_arg += 2;
4883 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004884 }
4885
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004886 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4887#ifdef SO_BINDTODEVICE
4888 if (!*args[cur_arg + 1]) {
4889 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 }
4894 if (curproxy->iface_name)
4895 free(curproxy->iface_name);
4896
4897 curproxy->iface_name = strdup(args[cur_arg + 1]);
4898 curproxy->iface_len = strlen(curproxy->iface_name);
4899 global.last_checks |= LSTCHK_NETADM;
4900#else
4901 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4902 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004905#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004906 cur_arg += 2;
4907 continue;
4908 }
4909 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4910 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_ALERT | ERR_FATAL;
4912 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004915 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4916 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4917 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4924 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928
4929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004930 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004931 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004937 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004938 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
4942 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004944 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004945 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 }
4949 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004951 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004952 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
4956 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004958 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004959 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004963 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004965 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004966 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004968 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004969 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004970 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004972 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004973 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004975 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004976 }
4977 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004979 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004980 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004982 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4987 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991
4992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004993 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004994 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005000 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005001 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
5005 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005007 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005008 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
5012 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005014 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005015 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
5019 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005021 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005022 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005023 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005026 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005028 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005029 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005030 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005031 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005034 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005035
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 if (curproxy == &defproxy) {
5037 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005041 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 if (*(args[1]) == 0) {
5045 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005049
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005050 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005051 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5052 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5053 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
5056 }
5057 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5058 }
5059 else if (*args[2]) {
5060 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5061 file, linenum, args[0], args[2]);
5062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
5064 }
5065
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005066 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005067 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005068 wl->s = strdup(args[1]);
5069 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005070 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5075 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005079
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005081 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005082 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
5086 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005088 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005089 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
5093 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005095 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005096 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 }
5100 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005109 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005110 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005111 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 }
5114 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005116 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005117 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
5121 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005122 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005123 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005124 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005125 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 }
5128 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005129 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005130
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 if (curproxy == &defproxy) {
5132 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005136 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 if (*(args[1]) == 0) {
5140 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
5144
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005145 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005146 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5147 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5148 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
5151 }
5152 err_code |= warnif_cond_requires_req(cond, file, linenum);
5153 }
5154 else if (*args[2]) {
5155 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5156 file, linenum, args[0], args[2]);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
5160
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005161 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005162 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005163 wl->s = strdup(args[1]);
5164 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166 else if (!strcmp(args[0], "errorloc") ||
5167 !strcmp(args[0], "errorloc302") ||
5168 !strcmp(args[0], "errorloc303")) { /* error location */
5169 int errnum, errlen;
5170 char *err;
5171
Willy Tarreau977b8e42006-12-29 14:19:17 +01005172 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005174
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005176 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
5180
5181 errnum = atol(args[1]);
5182 if (!strcmp(args[0], "errorloc303")) {
5183 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5184 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5185 } else {
5186 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5187 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5188 }
5189
Willy Tarreau0f772532006-12-23 20:51:41 +01005190 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5191 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005192 chunk_destroy(&curproxy->errmsg[rc]);
5193 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005194 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005197
5198 if (rc >= HTTP_ERR_SIZE) {
5199 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5200 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 free(err);
5202 }
5203 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005204 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5205 int errnum, errlen, fd;
5206 char *err;
5207 struct stat stat;
5208
5209 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005211
5212 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005213 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005216 }
5217
5218 fd = open(args[2], O_RDONLY);
5219 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5220 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5221 file, linenum, args[2], args[1]);
5222 if (fd >= 0)
5223 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005226 }
5227
Willy Tarreau27a674e2009-08-17 07:23:33 +02005228 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 errlen = stat.st_size;
5230 } else {
5231 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005232 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005234 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005235 }
5236
5237 err = malloc(errlen); /* malloc() must succeed during parsing */
5238 errnum = read(fd, err, errlen);
5239 if (errnum != errlen) {
5240 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5241 file, linenum, args[2], args[1]);
5242 close(fd);
5243 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005246 }
5247 close(fd);
5248
5249 errnum = atol(args[1]);
5250 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5251 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005252 chunk_destroy(&curproxy->errmsg[rc]);
5253 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005254 break;
5255 }
5256 }
5257
5258 if (rc >= HTTP_ERR_SIZE) {
5259 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5260 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005262 free(err);
5263 }
5264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005266 struct cfg_kw_list *kwl;
5267 int index;
5268
5269 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5270 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5271 if (kwl->kw[index].section != CFG_LISTEN)
5272 continue;
5273 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5274 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005275 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005276 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005277 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005278 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005279 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005282 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005283 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005284 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_WARN;
5286 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005287 }
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005289 }
5290 }
5291 }
5292
Willy Tarreau6daf3432008-01-22 16:44:08 +01005293 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreau93893792009-07-23 13:19:11 +02005297 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005298 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300}
5301
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005302int
5303cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5304{
5305
5306 int err_code = 0;
5307 const char *err;
5308
5309 if (!strcmp(args[0], "userlist")) { /* new userlist */
5310 struct userlist *newul;
5311
5312 if (!*args[1]) {
5313 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5314 file, linenum, args[0]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318
5319 err = invalid_char(args[1]);
5320 if (err) {
5321 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5322 file, linenum, *err, args[0], args[1]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
5327 for (newul = userlist; newul; newul = newul->next)
5328 if (!strcmp(newul->name, args[1])) {
5329 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5330 file, linenum, args[1]);
5331 err_code |= ERR_WARN;
5332 goto out;
5333 }
5334
5335 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5336 if (!newul) {
5337 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5338 err_code |= ERR_ALERT | ERR_ABORT;
5339 goto out;
5340 }
5341
5342 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5343 newul->name = strdup(args[1]);
5344
5345 if (!newul->groupusers | !newul->name) {
5346 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5347 err_code |= ERR_ALERT | ERR_ABORT;
5348 goto out;
5349 }
5350
5351 newul->next = userlist;
5352 userlist = newul;
5353
5354 } else if (!strcmp(args[0], "group")) { /* new group */
5355 int cur_arg, i;
5356 const char *err;
5357
5358 if (!*args[1]) {
5359 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5360 file, linenum, args[0]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364
5365 err = invalid_char(args[1]);
5366 if (err) {
5367 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5368 file, linenum, *err, args[0], args[1]);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372
5373 for(i = 0; i < userlist->grpcnt; i++)
5374 if (!strcmp(userlist->groups[i], args[1])) {
5375 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5376 file, linenum, args[1], userlist->name);
5377 err_code |= ERR_ALERT;
5378 goto out;
5379 }
5380
5381 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5382 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5383 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
5387
5388 cur_arg = 2;
5389
5390 while (*args[cur_arg]) {
5391 if (!strcmp(args[cur_arg], "users")) {
5392 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5393 cur_arg += 2;
5394 continue;
5395 } else {
5396 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5397 file, linenum, args[0]);
5398 err_code |= ERR_ALERT | ERR_FATAL;
5399 goto out;
5400 }
5401 }
5402
5403 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5404 } else if (!strcmp(args[0], "user")) { /* new user */
5405 struct auth_users *newuser;
5406 int cur_arg;
5407
5408 if (!*args[1]) {
5409 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5410 file, linenum, args[0]);
5411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
5413 }
5414
5415 for (newuser = userlist->users; newuser; newuser = newuser->next)
5416 if (!strcmp(newuser->user, args[1])) {
5417 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5418 file, linenum, args[1], userlist->name);
5419 err_code |= ERR_ALERT;
5420 goto out;
5421 }
5422
5423 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5424 if (!newuser) {
5425 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5426 err_code |= ERR_ALERT | ERR_ABORT;
5427 goto out;
5428 }
5429
5430 newuser->user = strdup(args[1]);
5431
5432 newuser->next = userlist->users;
5433 userlist->users = newuser;
5434
5435 cur_arg = 2;
5436
5437 while (*args[cur_arg]) {
5438 if (!strcmp(args[cur_arg], "password")) {
5439#ifndef CONFIG_HAP_CRYPT
5440 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5441 file, linenum);
5442 err_code |= ERR_ALERT;
5443#endif
5444 newuser->pass = strdup(args[cur_arg + 1]);
5445 cur_arg += 2;
5446 continue;
5447 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5448 newuser->pass = strdup(args[cur_arg + 1]);
5449 newuser->flags |= AU_O_INSECURE;
5450 cur_arg += 2;
5451 continue;
5452 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005453 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005454 cur_arg += 2;
5455 continue;
5456 } else {
5457 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5458 file, linenum, args[0]);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462 }
5463 } else {
5464 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 }
5467
5468out:
5469 return err_code;
5470}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471
5472/*
5473 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005474 * Returns the error code, 0 if OK, or any combination of :
5475 * - ERR_ABORT: must abort ASAP
5476 * - ERR_FATAL: we can continue parsing but not start the service
5477 * - ERR_WARN: a warning has been emitted
5478 * - ERR_ALERT: an alert has been emitted
5479 * Only the two first ones can stop processing, the two others are just
5480 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005482int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005484 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 FILE *f;
5486 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005488 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 if ((f=fopen(file,"r")) == NULL)
5491 return -1;
5492
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005493 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005494 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005495 char *end;
5496 char *args[MAX_LINE_ARGS + 1];
5497 char *line = thisline;
5498
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 linenum++;
5500
5501 end = line + strlen(line);
5502
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005503 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5504 /* Check if we reached the limit and the last char is not \n.
5505 * Watch out for the last line without the terminating '\n'!
5506 */
5507 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005508 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005509 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005510 }
5511
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005513 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 line++;
5515
5516 arg = 0;
5517 args[arg] = line;
5518
5519 while (*line && arg < MAX_LINE_ARGS) {
5520 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5521 * C equivalent value. Other combinations left unchanged (eg: \1).
5522 */
5523 if (*line == '\\') {
5524 int skip = 0;
5525 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5526 *line = line[1];
5527 skip = 1;
5528 }
5529 else if (line[1] == 'r') {
5530 *line = '\r';
5531 skip = 1;
5532 }
5533 else if (line[1] == 'n') {
5534 *line = '\n';
5535 skip = 1;
5536 }
5537 else if (line[1] == 't') {
5538 *line = '\t';
5539 skip = 1;
5540 }
5541 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005542 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 unsigned char hex1, hex2;
5544 hex1 = toupper(line[2]) - '0';
5545 hex2 = toupper(line[3]) - '0';
5546 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5547 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5548 *line = (hex1<<4) + hex2;
5549 skip = 3;
5550 }
5551 else {
5552 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 }
5555 }
5556 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005557 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 end -= skip;
5559 }
5560 line++;
5561 }
5562 else if (*line == '#' || *line == '\n' || *line == '\r') {
5563 /* end of string, end of loop */
5564 *line = 0;
5565 break;
5566 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005567 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005569 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005570 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 line++;
5572 args[++arg] = line;
5573 }
5574 else {
5575 line++;
5576 }
5577 }
5578
5579 /* empty line */
5580 if (!**args)
5581 continue;
5582
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005583 if (*line) {
5584 /* we had to stop due to too many args.
5585 * Let's terminate the string, print the offending part then cut the
5586 * last arg.
5587 */
5588 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5589 line++;
5590 *line = '\0';
5591
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005592 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005593 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 args[arg] = line;
5596 }
5597
Willy Tarreau540abe42007-05-02 20:50:16 +02005598 /* zero out remaining args and ensure that at least one entry
5599 * is zeroed out.
5600 */
5601 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 args[arg] = line;
5603 }
5604
Willy Tarreau3842f002009-06-14 11:39:52 +02005605 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005606 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005607 char *tmp;
5608
Willy Tarreau3842f002009-06-14 11:39:52 +02005609 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005610 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005611 for (arg=0; *args[arg+1]; arg++)
5612 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005613 *tmp = '\0'; // fix the next arg to \0
5614 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005615 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005616 else if (!strcmp(args[0], "default")) {
5617 kwm = KWM_DEF;
5618 for (arg=0; *args[arg+1]; arg++)
5619 args[arg] = args[arg+1]; // shift args after inversion
5620 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005621
William Lallemand0f99e342011-10-12 17:50:54 +02005622 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5623 strcmp(args[0], "log") != 0) {
5624 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005626 }
5627
Willy Tarreau977b8e42006-12-29 14:19:17 +01005628 if (!strcmp(args[0], "listen") ||
5629 !strcmp(args[0], "frontend") ||
5630 !strcmp(args[0], "backend") ||
5631 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005632 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005634 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005635 cursection = strdup(args[0]);
5636 }
5637 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005639 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005640 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005641 }
5642 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005643 confsect = CFG_USERLIST;
5644 free(cursection);
5645 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005646 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005647 else if (!strcmp(args[0], "peers")) {
5648 confsect = CFG_PEERS;
5649 free(cursection);
5650 cursection = strdup(args[0]);
5651 }
5652
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 /* else it's a section keyword */
5654
5655 switch (confsect) {
5656 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005657 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 break;
5659 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005660 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005662 case CFG_USERLIST:
5663 err_code |= cfg_parse_users(file, linenum, args, kwm);
5664 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005665 case CFG_PEERS:
5666 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5667 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005669 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005672
5673 if (err_code & ERR_ABORT)
5674 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005676 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005677 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005679 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005680}
5681
Willy Tarreaubb925012009-07-23 13:36:36 +02005682/*
5683 * Returns the error code, 0 if OK, or any combination of :
5684 * - ERR_ABORT: must abort ASAP
5685 * - ERR_FATAL: we can continue parsing but not start the service
5686 * - ERR_WARN: a warning has been emitted
5687 * - ERR_ALERT: an alert has been emitted
5688 * Only the two first ones can stop processing, the two others are just
5689 * indicators.
5690 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005691int check_config_validity()
5692{
5693 int cfgerr = 0;
5694 struct proxy *curproxy = NULL;
5695 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005696 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005697 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005698 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699
5700 /*
5701 * Now, check for the integrity of all that we have collected.
5702 */
5703
5704 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005705 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005707 /* first, we will invert the proxy list order */
5708 curproxy = NULL;
5709 while (proxy) {
5710 struct proxy *next;
5711
5712 next = proxy->next;
5713 proxy->next = curproxy;
5714 curproxy = proxy;
5715 if (!next)
5716 break;
5717 proxy = next;
5718 }
5719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005721 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005722 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005723 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005724 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005725 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005726 unsigned int next_id;
5727
5728 if (!curproxy->uuid) {
5729 /* proxy ID not set, use automatic numbering with first
5730 * spare entry starting with next_pxid.
5731 */
5732 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5733 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5734 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005735 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005736 next_pxid++;
5737
Willy Tarreau55ea7572007-06-17 19:56:27 +02005738
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005740 /* ensure we don't keep listeners uselessly bound */
5741 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 curproxy = curproxy->next;
5743 continue;
5744 }
5745
Willy Tarreauff01a212009-03-15 13:46:16 +01005746 switch (curproxy->mode) {
5747 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005748 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005749 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005750 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5751 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005752 cfgerr++;
5753 }
5754
5755 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005756 Warning("config : servers will be ignored for %s '%s'.\n",
5757 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005758 break;
5759
5760 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005761 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005762 break;
5763
5764 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005765 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005766 break;
5767 }
5768
5769 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005770 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5771 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 cfgerr++;
5773 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005774
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005775 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005776 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005777 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005778 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5779 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005780 cfgerr++;
5781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005783 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5785 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005786 cfgerr++;
5787 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005789 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005790 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5791 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005792 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005793 }
5794 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005795 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005796 /* If no LB algo is set in a backend, and we're not in
5797 * transparent mode, dispatch mode nor proxy mode, we
5798 * want to use balance roundrobin by default.
5799 */
5800 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5801 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005804
Willy Tarreau1620ec32011-08-06 17:05:02 +02005805 if (curproxy->options & PR_O_DISPATCH)
5806 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5807 else if (curproxy->options & PR_O_HTTP_PROXY)
5808 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5809 else if (curproxy->options & PR_O_TRANSP)
5810 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005811
Willy Tarreau1620ec32011-08-06 17:05:02 +02005812 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5813 if (curproxy->options & PR_O_DISABLE404) {
5814 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5815 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5816 err_code |= ERR_WARN;
5817 curproxy->options &= ~PR_O_DISABLE404;
5818 }
5819 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5820 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5821 "send-state", proxy_type_str(curproxy), curproxy->id);
5822 err_code |= ERR_WARN;
5823 curproxy->options &= ~PR_O2_CHK_SNDST;
5824 }
Willy Tarreauef781042010-01-27 11:53:01 +01005825 }
5826
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005827 /* if a default backend was specified, let's find it */
5828 if (curproxy->defbe.name) {
5829 struct proxy *target;
5830
Alex Williams96532db2009-11-01 21:27:13 -05005831 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005832 if (!target) {
5833 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5834 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005835 cfgerr++;
5836 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005837 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5838 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005839 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005840 } else {
5841 free(curproxy->defbe.name);
5842 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005843 /* we force the backend to be present on at least all of
5844 * the frontend's processes.
5845 */
5846 target->bind_proc = curproxy->bind_proc ?
5847 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005848
5849 /* Emit a warning if this proxy also has some servers */
5850 if (curproxy->srv) {
5851 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5852 curproxy->id);
5853 err_code |= ERR_WARN;
5854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 }
5856 }
5857
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005858 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005859 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5860 /* map jump target for ACT_SETBE in req_rep chain */
5861 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005862 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005863 struct proxy *target;
5864
Willy Tarreaua496b602006-12-17 23:15:24 +01005865 if (exp->action != ACT_SETBE)
5866 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005867
Alex Williams96532db2009-11-01 21:27:13 -05005868 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005869 if (!target) {
5870 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5871 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005872 cfgerr++;
5873 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005874 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5875 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005876 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005877 } else {
5878 free((void *)exp->replace);
5879 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005880 /* we force the backend to be present on at least all of
5881 * the frontend's processes.
5882 */
5883 target->bind_proc = curproxy->bind_proc ?
5884 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005885 }
5886 }
5887 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005888
5889 /* find the target proxy for 'use_backend' rules */
5890 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005891 struct proxy *target;
5892
Alex Williams96532db2009-11-01 21:27:13 -05005893 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005894
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005895 if (!target) {
5896 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5897 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005898 cfgerr++;
5899 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005900 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5901 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005902 cfgerr++;
5903 } else {
5904 free((void *)rule->be.name);
5905 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005906 /* we force the backend to be present on at least all of
5907 * the frontend's processes.
5908 */
5909 target->bind_proc = curproxy->bind_proc ?
5910 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005911 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005912 }
5913
5914 /* find the target proxy for 'use_backend' rules */
5915 list_for_each_entry(srule, &curproxy->server_rules, list) {
5916 struct server *target = findserver(curproxy, srule->srv.name);
5917
5918 if (!target) {
5919 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5920 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5921 cfgerr++;
5922 continue;
5923 }
5924 free((void *)srule->srv.name);
5925 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005926 }
5927
Emeric Brunb982a3d2010-01-04 15:45:53 +01005928 /* find the target table for 'stick' rules */
5929 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5930 struct proxy *target;
5931
Emeric Brun1d33b292010-01-04 15:47:17 +01005932 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5933 if (mrule->flags & STK_IS_STORE)
5934 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5935
Emeric Brunb982a3d2010-01-04 15:45:53 +01005936 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005937 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005938 else
5939 target = curproxy;
5940
5941 if (!target) {
5942 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5943 curproxy->id, mrule->table.name);
5944 cfgerr++;
5945 }
5946 else if (target->table.size == 0) {
5947 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5948 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5949 cfgerr++;
5950 }
Willy Tarreau12785782012-04-27 21:37:17 +02005951 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5952 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005953 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5954 cfgerr++;
5955 }
5956 else {
5957 free((void *)mrule->table.name);
5958 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005959 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005960 }
5961 }
5962
5963 /* find the target table for 'store response' rules */
5964 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5965 struct proxy *target;
5966
Emeric Brun1d33b292010-01-04 15:47:17 +01005967 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5968
Emeric Brunb982a3d2010-01-04 15:45:53 +01005969 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005970 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005971 else
5972 target = curproxy;
5973
5974 if (!target) {
5975 Alert("Proxy '%s': unable to find store table '%s'.\n",
5976 curproxy->id, mrule->table.name);
5977 cfgerr++;
5978 }
5979 else if (target->table.size == 0) {
5980 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5981 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5982 cfgerr++;
5983 }
Willy Tarreau12785782012-04-27 21:37:17 +02005984 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5985 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5987 cfgerr++;
5988 }
5989 else {
5990 free((void *)mrule->table.name);
5991 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005992 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005993 }
5994 }
5995
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005996 /* find the target table for 'tcp-request' layer 4 rules */
5997 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5998 struct proxy *target;
5999
Willy Tarreau56123282010-08-06 19:06:56 +02006000 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006001 continue;
6002
6003 if (trule->act_prm.trk_ctr.table.n)
6004 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6005 else
6006 target = curproxy;
6007
6008 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006009 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6010 curproxy->id, trule->act_prm.trk_ctr.table.n,
6011 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006012 cfgerr++;
6013 }
6014 else if (target->table.size == 0) {
6015 Alert("Proxy '%s': table '%s' used but not configured.\n",
6016 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6017 cfgerr++;
6018 }
6019 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006020 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 +02006021 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6022 cfgerr++;
6023 }
6024 else {
6025 free(trule->act_prm.trk_ctr.table.n);
6026 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006027 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006028 * to pass a list of counters to track and allocate them right here using
6029 * stktable_alloc_data_type().
6030 */
6031 }
6032 }
6033
Willy Tarreaud1f96522010-08-03 19:34:32 +02006034 /* find the target table for 'tcp-request' layer 6 rules */
6035 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6036 struct proxy *target;
6037
Willy Tarreau56123282010-08-06 19:06:56 +02006038 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006039 continue;
6040
6041 if (trule->act_prm.trk_ctr.table.n)
6042 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6043 else
6044 target = curproxy;
6045
6046 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006047 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6048 curproxy->id, trule->act_prm.trk_ctr.table.n,
6049 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006050 cfgerr++;
6051 }
6052 else if (target->table.size == 0) {
6053 Alert("Proxy '%s': table '%s' used but not configured.\n",
6054 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6055 cfgerr++;
6056 }
6057 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006058 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 +02006059 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6060 cfgerr++;
6061 }
6062 else {
6063 free(trule->act_prm.trk_ctr.table.n);
6064 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006065 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006066 * to pass a list of counters to track and allocate them right here using
6067 * stktable_alloc_data_type().
6068 */
6069 }
6070 }
6071
Emeric Brun32da3c42010-09-23 18:39:19 +02006072 if (curproxy->table.peers.name) {
6073 struct peers *curpeers = peers;
6074
6075 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6076 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6077 free((void *)curproxy->table.peers.name);
6078 curproxy->table.peers.p = peers;
6079 break;
6080 }
6081 }
6082
6083 if (!curpeers) {
6084 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6085 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006086 free((void *)curproxy->table.peers.name);
6087 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006088 cfgerr++;
6089 }
6090 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006091 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6092 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006093 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006094 cfgerr++;
6095 }
6096 }
6097
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006098 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006099 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006100 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6101 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6102 "proxy", curproxy->id);
6103 cfgerr++;
6104 goto out_uri_auth_compat;
6105 }
6106
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006107 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006108 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006109 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006110 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006111
Willy Tarreau95fa4692010-02-01 13:05:50 +01006112 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6113 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006114
6115 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006116 uri_auth_compat_req[i++] = "realm";
6117 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6118 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006119
Willy Tarreau95fa4692010-02-01 13:05:50 +01006120 uri_auth_compat_req[i++] = "unless";
6121 uri_auth_compat_req[i++] = "{";
6122 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6123 uri_auth_compat_req[i++] = "}";
6124 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006125
Willy Tarreauff011f22011-01-06 17:51:27 +01006126 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6127 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006128 cfgerr++;
6129 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006130 }
6131
Willy Tarreauff011f22011-01-06 17:51:27 +01006132 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006133
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006134 if (curproxy->uri_auth->auth_realm) {
6135 free(curproxy->uri_auth->auth_realm);
6136 curproxy->uri_auth->auth_realm = NULL;
6137 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006138
6139 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006140 }
6141out_uri_auth_compat:
6142
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006143 cfgerr += acl_find_targets(curproxy);
6144
Willy Tarreau2738a142006-07-08 17:28:09 +02006145 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006146 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006147 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006148 (!curproxy->timeout.connect ||
6149 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006150 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006151 " | While not properly invalid, you will certainly encounter various problems\n"
6152 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006153 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006154 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006155 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006156 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006157
Willy Tarreau1fa31262007-12-03 00:36:16 +01006158 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6159 * We must still support older configurations, so let's find out whether those
6160 * parameters have been set or must be copied from contimeouts.
6161 */
6162 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006163 if (!curproxy->timeout.tarpit ||
6164 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006165 /* tarpit timeout not set. We search in the following order:
6166 * default.tarpit, curr.connect, default.connect.
6167 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006168 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006169 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006170 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006171 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006172 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006173 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006174 }
6175 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006176 (!curproxy->timeout.queue ||
6177 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006178 /* queue timeout not set. We search in the following order:
6179 * default.queue, curr.connect, default.connect.
6180 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006181 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006182 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006183 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006184 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006185 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006186 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006187 }
6188 }
6189
Willy Tarreau1620ec32011-08-06 17:05:02 +02006190 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006191 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6192 curproxy->check_req = (char *)malloc(curproxy->check_len);
6193 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006194 }
6195
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006196 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006197 if (curproxy->nb_req_cap) {
6198 if (curproxy->mode == PR_MODE_HTTP) {
6199 curproxy->req_cap_pool = create_pool("ptrcap",
6200 curproxy->nb_req_cap * sizeof(char *),
6201 MEM_F_SHARED);
6202 } else {
6203 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6204 proxy_type_str(curproxy), curproxy->id);
6205 err_code |= ERR_WARN;
6206 curproxy->to_log &= ~LW_REQHDR;
6207 curproxy->nb_req_cap = 0;
6208 }
6209 }
6210
6211 if (curproxy->nb_rsp_cap) {
6212 if (curproxy->mode == PR_MODE_HTTP) {
6213 curproxy->rsp_cap_pool = create_pool("ptrcap",
6214 curproxy->nb_rsp_cap * sizeof(char *),
6215 MEM_F_SHARED);
6216 } else {
6217 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6218 proxy_type_str(curproxy), curproxy->id);
6219 err_code |= ERR_WARN;
6220 curproxy->to_log &= ~LW_REQHDR;
6221 curproxy->nb_rsp_cap = 0;
6222 }
6223 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006224
Willy Tarreau196729e2012-05-31 19:30:26 +02006225 /* compile the log format */
6226 if (curproxy->logformat_string)
6227 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6228
6229 if (curproxy->uniqueid_format_string)
6230 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6231
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 /* first, we will invert the servers list order */
6233 newsrv = NULL;
6234 while (curproxy->srv) {
6235 struct server *next;
6236
6237 next = curproxy->srv->next;
6238 curproxy->srv->next = newsrv;
6239 newsrv = curproxy->srv;
6240 if (!next)
6241 break;
6242 curproxy->srv = next;
6243 }
6244
Willy Tarreaudd701652010-05-25 23:03:02 +02006245 /* assign automatic UIDs to servers which don't have one yet */
6246 next_id = 1;
6247 newsrv = curproxy->srv;
6248 while (newsrv != NULL) {
6249 if (!newsrv->puid) {
6250 /* server ID not set, use automatic numbering with first
6251 * spare entry starting with next_svid.
6252 */
6253 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6254 newsrv->conf.id.key = newsrv->puid = next_id;
6255 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6256 }
6257 next_id++;
6258 newsrv = newsrv->next;
6259 }
6260
Willy Tarreau20697042007-11-15 23:26:18 +01006261 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006262 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006263
Willy Tarreau62c3be22012-01-20 13:12:32 +01006264 /*
6265 * If this server supports a maxconn parameter, it needs a dedicated
6266 * tasks to fill the emptied slots when a connection leaves.
6267 * Also, resolve deferred tracking dependency if needed.
6268 */
6269 newsrv = curproxy->srv;
6270 while (newsrv != NULL) {
6271 if (newsrv->minconn > newsrv->maxconn) {
6272 /* Only 'minconn' was specified, or it was higher than or equal
6273 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6274 * this will avoid further useless expensive computations.
6275 */
6276 newsrv->maxconn = newsrv->minconn;
6277 } else if (newsrv->maxconn && !newsrv->minconn) {
6278 /* minconn was not specified, so we set it to maxconn */
6279 newsrv->minconn = newsrv->maxconn;
6280 }
6281
6282 if (newsrv->trackit) {
6283 struct proxy *px;
6284 struct server *srv;
6285 char *pname, *sname;
6286
6287 pname = newsrv->trackit;
6288 sname = strrchr(pname, '/');
6289
6290 if (sname)
6291 *sname++ = '\0';
6292 else {
6293 sname = pname;
6294 pname = NULL;
6295 }
6296
6297 if (pname) {
6298 px = findproxy(pname, PR_CAP_BE);
6299 if (!px) {
6300 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6301 proxy_type_str(curproxy), curproxy->id,
6302 newsrv->id, pname);
6303 cfgerr++;
6304 goto next_srv;
6305 }
6306 } else
6307 px = curproxy;
6308
6309 srv = findserver(px, sname);
6310 if (!srv) {
6311 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6312 proxy_type_str(curproxy), curproxy->id,
6313 newsrv->id, sname);
6314 cfgerr++;
6315 goto next_srv;
6316 }
6317
6318 if (!(srv->state & SRV_CHECKED)) {
6319 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6320 "tracking as it does not have checks enabled.\n",
6321 proxy_type_str(curproxy), curproxy->id,
6322 newsrv->id, px->id, srv->id);
6323 cfgerr++;
6324 goto next_srv;
6325 }
6326
6327 if (curproxy != px &&
6328 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6329 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6330 "tracking: disable-on-404 option inconsistency.\n",
6331 proxy_type_str(curproxy), curproxy->id,
6332 newsrv->id, px->id, srv->id);
6333 cfgerr++;
6334 goto next_srv;
6335 }
6336
6337 /* if the other server is forced disabled, we have to do the same here */
6338 if (srv->state & SRV_MAINTAIN) {
6339 newsrv->state |= SRV_MAINTAIN;
6340 newsrv->state &= ~SRV_RUNNING;
6341 newsrv->health = 0;
6342 }
6343
6344 newsrv->track = srv;
6345 newsrv->tracknext = srv->tracknext;
6346 srv->tracknext = newsrv;
6347
6348 free(newsrv->trackit);
6349 newsrv->trackit = NULL;
6350 }
6351 next_srv:
6352 newsrv = newsrv->next;
6353 }
6354
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006355 /* We have to initialize the server lookup mechanism depending
6356 * on what LB algorithm was choosen.
6357 */
6358
6359 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6360 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6361 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006362 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6363 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6364 init_server_map(curproxy);
6365 } else {
6366 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6367 fwrr_init_server_groups(curproxy);
6368 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006369 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006370
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006371 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006372 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6373 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6374 fwlc_init_server_tree(curproxy);
6375 } else {
6376 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6377 fas_init_server_tree(curproxy);
6378 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006379 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006380
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006381 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006382 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6383 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6384 chash_init_server_tree(curproxy);
6385 } else {
6386 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6387 init_server_map(curproxy);
6388 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006389 break;
6390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391
6392 if (curproxy->options & PR_O_LOGASAP)
6393 curproxy->to_log &= ~LW_BYTES;
6394
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006395 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006396 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006397 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6398 proxy_type_str(curproxy), curproxy->id);
6399 err_code |= ERR_WARN;
6400 }
6401
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006402 if (curproxy->mode != PR_MODE_HTTP) {
6403 int optnum;
6404
6405 if (curproxy->options & PR_O_COOK_ANY) {
6406 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6407 proxy_type_str(curproxy), curproxy->id);
6408 err_code |= ERR_WARN;
6409 }
6410
6411 if (curproxy->uri_auth) {
6412 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6413 proxy_type_str(curproxy), curproxy->id);
6414 err_code |= ERR_WARN;
6415 curproxy->uri_auth = NULL;
6416 }
6417
Willy Tarreau87cf5142011-08-19 22:57:24 +02006418 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006419 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6420 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6421 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006422 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006423 }
6424
6425 if (curproxy->options & PR_O_ORGTO) {
6426 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6427 "originalto", proxy_type_str(curproxy), curproxy->id);
6428 err_code |= ERR_WARN;
6429 curproxy->options &= ~PR_O_ORGTO;
6430 }
6431
6432 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6433 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6434 (curproxy->cap & cfg_opts[optnum].cap) &&
6435 (curproxy->options & cfg_opts[optnum].val)) {
6436 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6437 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6438 err_code |= ERR_WARN;
6439 curproxy->options &= ~cfg_opts[optnum].val;
6440 }
6441 }
6442
6443 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6444 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6445 (curproxy->cap & cfg_opts2[optnum].cap) &&
6446 (curproxy->options2 & cfg_opts2[optnum].val)) {
6447 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6448 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6449 err_code |= ERR_WARN;
6450 curproxy->options2 &= ~cfg_opts2[optnum].val;
6451 }
6452 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006453
Willy Tarreauefa5f512010-03-30 20:13:29 +02006454#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006455 if (curproxy->bind_hdr_occ) {
6456 curproxy->bind_hdr_occ = 0;
6457 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6458 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6459 err_code |= ERR_WARN;
6460 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006461#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006462 }
6463
Willy Tarreaubaaee002006-06-26 02:48:02 +02006464 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006465 * ensure that we're not cross-dressing a TCP server into HTTP.
6466 */
6467 newsrv = curproxy->srv;
6468 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006469 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006470 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6471 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006472 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006473 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006474
Willy Tarreau0cec3312011-10-31 13:49:26 +01006475 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6476 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6477 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6478 err_code |= ERR_WARN;
6479 }
6480
Willy Tarreauefa5f512010-03-30 20:13:29 +02006481#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006482 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6483 newsrv->bind_hdr_occ = 0;
6484 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6485 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6486 err_code |= ERR_WARN;
6487 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006488#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006489 newsrv = newsrv->next;
6490 }
6491
Willy Tarreauc1a21672009-08-16 22:37:44 +02006492 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006493 curproxy->accept = frontend_accept;
6494
Willy Tarreauc1a21672009-08-16 22:37:44 +02006495 if (curproxy->tcp_req.inspect_delay ||
6496 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006497 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006498
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006499 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006500 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006501 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006502 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006503
6504 /* both TCP and HTTP must check switching rules */
6505 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6506 }
6507
6508 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006509 if (curproxy->tcp_req.inspect_delay ||
6510 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6511 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6512
Emeric Brun97679e72010-09-23 17:56:44 +02006513 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6514 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6515
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006516 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006517 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006518 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006519 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006520
6521 /* If the backend does requires RDP cookie persistence, we have to
6522 * enable the corresponding analyser.
6523 */
6524 if (curproxy->options2 & PR_O2_RDPC_PRST)
6525 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6526 }
6527
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006528 listener = NULL;
6529 while (curproxy->listen) {
6530 struct listener *next;
6531
6532 next = curproxy->listen->next;
6533 curproxy->listen->next = listener;
6534 listener = curproxy->listen;
6535
6536 if (!next)
6537 break;
6538
6539 curproxy->listen = next;
6540 }
6541
Willy Tarreaue6b98942007-10-29 01:09:36 +01006542 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006543 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006544 listener = curproxy->listen;
6545 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006546 if (!listener->luid) {
6547 /* listener ID not set, use automatic numbering with first
6548 * spare entry starting with next_luid.
6549 */
6550 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6551 listener->conf.id.key = listener->luid = next_id;
6552 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006553 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006554 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006555
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006556 /* enable separate counters */
6557 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6558 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6559 if (!listener->name) {
6560 sprintf(trash, "sock-%d", listener->luid);
6561 listener->name = strdup(trash);
6562 }
6563 }
6564
Willy Tarreaue6b98942007-10-29 01:09:36 +01006565 if (curproxy->options & PR_O_TCP_NOLING)
6566 listener->options |= LI_O_NOLINGER;
6567 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006568 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006569 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006570 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006571 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006572 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006573 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006574
Willy Tarreau8a956912010-10-15 14:27:08 +02006575 if (listener->options & LI_O_ACC_PROXY)
6576 listener->analysers |= AN_REQ_DECODE_PROXY;
6577
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006578 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6579 listener->options |= LI_O_TCP_RULES;
6580
Willy Tarreaude3041d2010-05-31 10:56:17 +02006581 if (curproxy->mon_mask.s_addr)
6582 listener->options |= LI_O_CHK_MONNET;
6583
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006584 /* smart accept mode is automatic in HTTP mode */
6585 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6586 (curproxy->mode == PR_MODE_HTTP &&
6587 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6588 listener->options |= LI_O_NOQUICKACK;
6589
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006590 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006591 listener = listener->next;
6592 }
6593
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006594 /* Check multi-process mode compatibility for the current proxy */
6595 if (global.nbproc > 1) {
6596 int nbproc = 0;
6597 if (curproxy->bind_proc) {
6598 int proc;
6599 for (proc = 0; proc < global.nbproc; proc++) {
6600 if (curproxy->bind_proc & (1 << proc)) {
6601 nbproc++;
6602 }
6603 }
6604 } else {
6605 nbproc = global.nbproc;
6606 }
6607 if (curproxy->table.peers.name) {
6608 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6609 curproxy->id);
6610 cfgerr++;
6611 }
6612 if (nbproc > 1) {
6613 if (curproxy->uri_auth) {
6614 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6615 curproxy->id);
6616 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6617 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6618 curproxy->id);
6619 }
6620 }
6621 if (curproxy->appsession_name) {
6622 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6623 curproxy->id);
6624 }
6625 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6626 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6627 curproxy->id);
6628 }
6629 }
6630 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006631
6632 /* create the task associated with the proxy */
6633 curproxy->task = task_new();
6634 if (curproxy->task) {
6635 curproxy->task->context = curproxy;
6636 curproxy->task->process = manage_proxy;
6637 /* no need to queue, it will be done automatically if some
6638 * listener gets limited.
6639 */
6640 curproxy->task->expire = TICK_ETERNITY;
6641 } else {
6642 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6643 curproxy->id);
6644 cfgerr++;
6645 }
6646
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 curproxy = curproxy->next;
6648 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006649
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006650 /* Check multi-process mode compatibility */
6651 if (global.nbproc > 1) {
6652 if (global.stats_fe) {
6653 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6654 }
6655 }
6656
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006657 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6658 struct auth_users *curuser;
6659 int g;
6660
6661 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6662 unsigned int group_mask = 0;
6663 char *group = NULL;
6664
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006665 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006666 continue;
6667
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006668 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006669
6670 for (g = 0; g < curuserlist->grpcnt; g++)
6671 if (!strcmp(curuserlist->groups[g], group))
6672 break;
6673
6674 if (g == curuserlist->grpcnt) {
6675 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6676 curuserlist->name, group, curuser->user);
6677 err_code |= ERR_ALERT | ERR_FATAL;
6678 goto out;
6679 }
6680
6681 group_mask |= (1 << g);
6682 }
6683
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006684 free(curuser->u.groups);
6685 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006686 }
6687
6688 for (g = 0; g < curuserlist->grpcnt; g++) {
6689 char *user = NULL;
6690
6691 if (!curuserlist->groupusers[g])
6692 continue;
6693
6694 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6695 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6696 if (!strcmp(curuser->user, user))
6697 break;
6698
6699 if (!curuser) {
6700 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6701 curuserlist->name, user, curuserlist->groups[g]);
6702 err_code |= ERR_ALERT | ERR_FATAL;
6703 goto out;
6704 }
6705
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006706 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006707 }
6708
6709 free(curuserlist->groupusers[g]);
6710 }
6711
6712 free(curuserlist->groupusers);
6713
6714#ifdef DEBUG_AUTH
6715 for (g = 0; g < curuserlist->grpcnt; g++) {
6716 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6717
6718 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006719 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720 fprintf(stderr, " %s", curuser->user);
6721 }
6722
6723 fprintf(stderr, "\n");
6724 }
6725#endif
6726
Willy Tarreaufbb78422011-06-05 15:38:35 +02006727 }
6728
6729 /* automatically compute fullconn if not set. We must not do it in the
6730 * loop above because cross-references are not yet fully resolved.
6731 */
6732 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6733 /* If <fullconn> is not set, let's set it to 10% of the sum of
6734 * the possible incoming frontend's maxconns.
6735 */
6736 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6737 struct proxy *fe;
6738 int total = 0;
6739
6740 /* sum up the number of maxconns of frontends which
6741 * reference this backend at least once or which are
6742 * the same one ('listen').
6743 */
6744 for (fe = proxy; fe; fe = fe->next) {
6745 struct switching_rule *rule;
6746 struct hdr_exp *exp;
6747 int found = 0;
6748
6749 if (!(fe->cap & PR_CAP_FE))
6750 continue;
6751
6752 if (fe == curproxy) /* we're on a "listen" instance */
6753 found = 1;
6754
6755 if (fe->defbe.be == curproxy) /* "default_backend" */
6756 found = 1;
6757
6758 /* check if a "use_backend" rule matches */
6759 if (!found) {
6760 list_for_each_entry(rule, &fe->switching_rules, list) {
6761 if (rule->be.backend == curproxy) {
6762 found = 1;
6763 break;
6764 }
6765 }
6766 }
6767
6768 /* check if a "reqsetbe" rule matches */
6769 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6770 if (exp->action == ACT_SETBE &&
6771 (struct proxy *)exp->replace == curproxy) {
6772 found = 1;
6773 break;
6774 }
6775 }
6776
6777 /* now we've checked all possible ways to reference a backend
6778 * from a frontend.
6779 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006780 if (!found)
6781 continue;
6782 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006783 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006784 /* we have the sum of the maxconns in <total>. We only
6785 * keep 10% of that sum to set the default fullconn, with
6786 * a hard minimum of 1 (to avoid a divide by zero).
6787 */
6788 curproxy->fullconn = (total + 9) / 10;
6789 if (!curproxy->fullconn)
6790 curproxy->fullconn = 1;
6791 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 }
6793
Willy Tarreau056f5682010-06-06 15:51:11 +02006794 /* initialize stick-tables on backend capable proxies. This must not
6795 * be done earlier because the data size may be discovered while parsing
6796 * other proxies.
6797 */
6798 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006799 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006800
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006801 /*
6802 * Recount currently required checks.
6803 */
6804
6805 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6806 int optnum;
6807
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006808 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6809 if (curproxy->options & cfg_opts[optnum].val)
6810 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006811
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006812 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6813 if (curproxy->options2 & cfg_opts2[optnum].val)
6814 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006815 }
6816
Willy Tarreau122541c2011-09-07 21:24:49 +02006817 if (peers) {
6818 struct peers *curpeers = peers, **last;
6819 struct peer *p, *pb;
6820
6821 /* Remove all peers sections which don't have a valid listener.
6822 * This can happen when a peers section is never referenced and
6823 * does not contain a local peer.
6824 */
6825 last = &peers;
6826 while (*last) {
6827 curpeers = *last;
6828 if (curpeers->peers_fe) {
6829 last = &curpeers->next;
6830 continue;
6831 }
6832
6833 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6834 curpeers->id, localpeer);
6835
6836 p = curpeers->remote;
6837 while (p) {
6838 pb = p->next;
6839 free(p->id);
6840 free(p);
6841 p = pb;
6842 }
6843
6844 /* Destroy and unlink this curpeers section.
6845 * Note: curpeers is backed up into *last.
6846 */
6847 free(curpeers->id);
6848 curpeers = curpeers->next;
6849 free(*last);
6850 *last = curpeers;
6851 }
6852 }
6853
Willy Tarreauac1932d2011-10-24 19:14:41 +02006854 if (!global.tune.max_http_hdr)
6855 global.tune.max_http_hdr = MAX_HTTP_HDR;
6856
Willy Tarreau34eb6712011-10-24 18:15:04 +02006857 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006858 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006859 MEM_F_SHARED);
6860
Willy Tarreaubb925012009-07-23 13:36:36 +02006861 if (cfgerr > 0)
6862 err_code |= ERR_ALERT | ERR_FATAL;
6863 out:
6864 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006865}
6866
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006867/*
6868 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6869 * parsing sessions.
6870 */
6871void cfg_register_keywords(struct cfg_kw_list *kwl)
6872{
6873 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6874}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006876/*
6877 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6878 */
6879void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6880{
6881 LIST_DEL(&kwl->list);
6882 LIST_INIT(&kwl->list);
6883}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006884
6885/*
6886 * Local variables:
6887 * c-indent-level: 8
6888 * c-basic-offset: 8
6889 * End:
6890 */