blob: 49d1dbe02190d5973e6f9bc7b65ad5a1b17f5978 [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;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100268 l->state = LI_INIT;
269
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100270 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100272 tcpv4_add_listener(l);
273 }
Emeric Bruned760922010-10-22 17:59:25 +0200274 else if (ss.ss_family == AF_INET6) {
275 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
276 tcpv6_add_listener(l);
277 }
278 else {
279 l->perm.ux.gid = l->perm.ux.uid = -1;
280 l->perm.ux.mode = 0;
281 uxst_add_listener(l);
282 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200283
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200284 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 } /* end for(port) */
287 } /* end while(next) */
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 fail:
291 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200292 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293}
294
Willy Tarreau977b8e42006-12-29 14:19:17 +0100295/*
296 * Sends a warning if proxy <proxy> does not have at least one of the
297 * capabilities in <cap>. An optionnal <hint> may be added at the end
298 * of the warning to help the user. Returns 1 if a warning was emitted
299 * or 0 if the condition is valid.
300 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100301int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302{
303 char *msg;
304
305 switch (cap) {
306 case PR_CAP_BE: msg = "no backend"; break;
307 case PR_CAP_FE: msg = "no frontend"; break;
308 case PR_CAP_RS: msg = "no ruleset"; break;
309 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
310 default: msg = "not enough"; break;
311 }
312
313 if (!(proxy->cap & cap)) {
314 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100315 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100316 return 1;
317 }
318 return 0;
319}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320
Willy Tarreau61d18892009-03-31 10:49:21 +0200321/* Report a warning if a rule is placed after a 'block' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100324int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200325{
326 if (!LIST_ISEMPTY(&proxy->block_cond)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
334/* Report a warning if a rule is placed after a reqrewrite rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
339 if (proxy->req_exp) {
340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
347/* Report a warning if a rule is placed after a reqadd rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100350int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200351{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100352 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200353 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
360/* Report a warning if a rule is placed after a redirect rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a 'use_backend' rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
378 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100387int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200388{
389 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
390 warnif_rule_after_reqadd(proxy, file, line, arg) ||
391 warnif_rule_after_redirect(proxy, file, line, arg) ||
392 warnif_rule_after_use_backend(proxy, file, line, arg);
393}
394
395/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100396int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200397{
398 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100410/* Report it if a request ACL condition uses some response-only parameters. It
411 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
412 * Note that <cond> may be NULL and then will be ignored.
413 */
414static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
415{
416 struct acl *acl;
417
418 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
419 return 0;
420
421 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
422 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
423 file, line, acl ? acl->name : "(unknown)");
424 return ERR_WARN;
425}
426
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100427/* Report it if a request ACL condition uses some request-only volatile parameters.
428 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
429 * Note that <cond> may be NULL and then will be ignored.
430 */
431static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
432{
433 struct acl *acl;
434
435 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
436 return 0;
437
438 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
439 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
440 file, line, acl ? acl->name : "(unknown)");
441 return ERR_WARN;
442}
443
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100444
Willy Tarreaubaaee002006-06-26 02:48:02 +0200445/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200446 * parse a line in a <global> section. Returns the error code, 0 if OK, or
447 * any combination of :
448 * - ERR_ABORT: must abort ASAP
449 * - ERR_FATAL: we can continue parsing but not start the service
450 * - ERR_WARN: a warning has been emitted
451 * - ERR_ALERT: an alert has been emitted
452 * Only the two first ones can stop processing, the two others are just
453 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200455int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456{
Willy Tarreau058e9072009-07-20 09:30:05 +0200457 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200458 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459
460 if (!strcmp(args[0], "global")) { /* new section */
461 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463 }
464 else if (!strcmp(args[0], "daemon")) {
465 global.mode |= MODE_DAEMON;
466 }
467 else if (!strcmp(args[0], "debug")) {
468 global.mode |= MODE_DEBUG;
469 }
470 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100471 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100474 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200475 }
476 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100480 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100482 else if (!strcmp(args[0], "nosplice")) {
483 global.tune.options &= ~GTUNE_USE_SPLICE;
484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 else if (!strcmp(args[0], "quiet")) {
486 global.mode |= MODE_QUIET;
487 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200488 else if (!strcmp(args[0], "tune.maxpollevents")) {
489 if (global.tune.maxpollevents != 0) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200491 err_code |= ERR_ALERT;
492 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200498 }
499 global.tune.maxpollevents = atol(args[1]);
500 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100501 else if (!strcmp(args[0], "tune.maxaccept")) {
502 if (global.tune.maxaccept != 0) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200504 err_code |= ERR_ALERT;
505 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100511 }
512 global.tune.maxaccept = atol(args[1]);
513 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200514 else if (!strcmp(args[0], "tune.chksize")) {
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
517 err_code |= ERR_ALERT | ERR_FATAL;
518 goto out;
519 }
520 global.tune.chksize = atol(args[1]);
521 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200522 else if (!strcmp(args[0], "tune.bufsize")) {
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527 }
528 global.tune.bufsize = atol(args[1]);
529 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
530 global.tune.maxrewrite = global.tune.bufsize / 2;
531 }
532 else if (!strcmp(args[0], "tune.maxrewrite")) {
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
537 }
538 global.tune.maxrewrite = atol(args[1]);
539 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
540 global.tune.maxrewrite = global.tune.bufsize / 2;
541 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100542 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
543 if (global.tune.client_rcvbuf != 0) {
544 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
545 err_code |= ERR_ALERT;
546 goto out;
547 }
548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
550 err_code |= ERR_ALERT | ERR_FATAL;
551 goto out;
552 }
553 global.tune.client_rcvbuf = atol(args[1]);
554 }
555 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
556 if (global.tune.server_rcvbuf != 0) {
557 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT;
559 goto out;
560 }
561 if (*(args[1]) == 0) {
562 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT | ERR_FATAL;
564 goto out;
565 }
566 global.tune.server_rcvbuf = atol(args[1]);
567 }
568 else if (!strcmp(args[0], "tune.sndbuf.client")) {
569 if (global.tune.client_sndbuf != 0) {
570 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT;
572 goto out;
573 }
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 global.tune.client_sndbuf = atol(args[1]);
580 }
581 else if (!strcmp(args[0], "tune.sndbuf.server")) {
582 if (global.tune.server_sndbuf != 0) {
583 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT;
585 goto out;
586 }
587 if (*(args[1]) == 0) {
588 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
589 err_code |= ERR_ALERT | ERR_FATAL;
590 goto out;
591 }
592 global.tune.server_sndbuf = atol(args[1]);
593 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200594 else if (!strcmp(args[0], "tune.pipesize")) {
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.pipesize = atol(args[1]);
601 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200602 else if (!strcmp(args[0], "tune.http.maxhdr")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.max_http_hdr = atol(args[1]);
609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 else if (!strcmp(args[0], "uid")) {
611 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200612 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT;
614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620 }
621 global.uid = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "gid")) {
624 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200625 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 }
634 global.gid = atol(args[1]);
635 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200636 /* user/group name handling */
637 else if (!strcmp(args[0], "user")) {
638 struct passwd *ha_user;
639 if (global.uid != 0) {
640 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200641 err_code |= ERR_ALERT;
642 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200643 }
644 errno = 0;
645 ha_user = getpwnam(args[1]);
646 if (ha_user != NULL) {
647 global.uid = (int)ha_user->pw_uid;
648 }
649 else {
650 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 +0200651 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200652 }
653 }
654 else if (!strcmp(args[0], "group")) {
655 struct group *ha_group;
656 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200657 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200658 err_code |= ERR_ALERT;
659 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 errno = 0;
662 ha_group = getgrnam(args[1]);
663 if (ha_group != NULL) {
664 global.gid = (int)ha_group->gr_gid;
665 }
666 else {
667 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 +0200668 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200669 }
670 }
671 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 else if (!strcmp(args[0], "nbproc")) {
673 if (global.nbproc != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200675 err_code |= ERR_ALERT;
676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683 global.nbproc = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "maxconn")) {
686 if (global.maxconn != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 global.maxconn = atol(args[1]);
697#ifdef SYSTEM_MAXCONN
698 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
699 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);
700 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 }
703#endif /* SYSTEM_MAXCONN */
704 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200705 else if (!strcmp(args[0], "maxconnrate")) {
706 if (global.cps_lim != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
708 err_code |= ERR_ALERT;
709 goto out;
710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.cps_lim = atol(args[1]);
717 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100718 else if (!strcmp(args[0], "maxpipes")) {
719 if (global.maxpipes != 0) {
720 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT;
722 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 }
724 if (*(args[1]) == 0) {
725 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100728 }
729 global.maxpipes = atol(args[1]);
730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 else if (!strcmp(args[0], "ulimit-n")) {
732 if (global.rlimit_nofile != 0) {
733 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT;
735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 }
737 if (*(args[1]) == 0) {
738 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 }
742 global.rlimit_nofile = atol(args[1]);
743 }
744 else if (!strcmp(args[0], "chroot")) {
745 if (global.chroot != NULL) {
746 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 }
755 global.chroot = strdup(args[1]);
756 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200757 else if (!strcmp(args[0], "description")) {
758 int i, len=0;
759 char *d;
760
761 if (!*args[1]) {
762 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
763 file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767
768 for(i=1; *args[i]; i++)
769 len += strlen(args[i])+1;
770
771 if (global.desc)
772 free(global.desc);
773
774 global.desc = d = (char *)calloc(1, len);
775
776 d += sprintf(d, "%s", args[1]);
777 for(i=2; *args[i]; i++)
778 d += sprintf(d, " %s", args[i]);
779 }
780 else if (!strcmp(args[0], "node")) {
781 int i;
782 char c;
783
784 for (i=0; args[1][i]; i++) {
785 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100786 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
787 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200788 break;
789 }
790
791 if (!i || args[1][i]) {
792 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
793 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
794 file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798
799 if (global.node)
800 free(global.node);
801
802 global.node = strdup(args[1]);
803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 else if (!strcmp(args[0], "pidfile")) {
805 if (global.pidfile != NULL) {
806 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 }
810 if (*(args[1]) == 0) {
811 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 }
815 global.pidfile = strdup(args[1]);
816 }
Emeric Bruned760922010-10-22 17:59:25 +0200817 else if (!strcmp(args[0], "unix-bind")) {
818 int cur_arg = 1;
819 while (*(args[cur_arg])) {
820 if (!strcmp(args[cur_arg], "prefix")) {
821 if (global.unix_bind.prefix != NULL) {
822 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
823 err_code |= ERR_ALERT;
824 cur_arg += 2;
825 continue;
826 }
827
828 if (*(args[cur_arg+1]) == 0) {
829 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 global.unix_bind.prefix = strdup(args[cur_arg+1]);
834 cur_arg += 2;
835 continue;
836 }
837
838 if (!strcmp(args[cur_arg], "mode")) {
839
840 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
841 cur_arg += 2;
842 continue;
843 }
844
845 if (!strcmp(args[cur_arg], "uid")) {
846
847 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
848 cur_arg += 2;
849 continue;
850 }
851
852 if (!strcmp(args[cur_arg], "gid")) {
853
854 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
855 cur_arg += 2;
856 continue;
857 }
858
859 if (!strcmp(args[cur_arg], "user")) {
860 struct passwd *user;
861
862 user = getpwnam(args[cur_arg + 1]);
863 if (!user) {
864 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
865 file, linenum, args[0], args[cur_arg + 1 ]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
869
870 global.unix_bind.ux.uid = user->pw_uid;
871 cur_arg += 2;
872 continue;
873 }
874
875 if (!strcmp(args[cur_arg], "group")) {
876 struct group *group;
877
878 group = getgrnam(args[cur_arg + 1]);
879 if (!group) {
880 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
881 file, linenum, args[0], args[cur_arg + 1 ]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 global.unix_bind.ux.gid = group->gr_gid;
887 cur_arg += 2;
888 continue;
889 }
890
Willy Tarreaub48f9582011-09-05 01:17:06 +0200891 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200892 file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
896 }
William Lallemand0f99e342011-10-12 17:50:54 +0200897 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
898 /* delete previous herited or defined syslog servers */
899 struct logsrv *back;
900 struct logsrv *tmp;
901
902 if (*(args[1]) != 0) {
903 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907
908 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
909 LIST_DEL(&tmp->list);
910 free(tmp);
911 }
912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200914 struct logsrv *logsrv;
915
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 if (*(args[1]) == 0 || *(args[2]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 }
William Lallemand0f99e342011-10-12 17:50:54 +0200921
922 logsrv = calloc(1, sizeof(struct logsrv));
923
924 logsrv->facility = get_log_facility(args[2]);
925 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200928 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200933 logsrv->level = get_log_level(args[3]);
934 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200937 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 }
939 }
940
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200942 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200943 logsrv->minlvl = get_log_level(args[4]);
944 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200947 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200948 }
949 }
950
Robert Tsai81ae1952007-12-05 10:47:29 +0100951 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100952 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100953 if (!sk) {
954 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100955 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200957 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100958 goto out;
959 }
William Lallemand0f99e342011-10-12 17:50:54 +0200960 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100961 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100962 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100963 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
965 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200966 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100967 goto out;
968 }
William Lallemand0f99e342011-10-12 17:50:54 +0200969 logsrv->addr = *sk;
970 if (!get_host_port(&logsrv->addr))
971 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973
William Lallemand0f99e342011-10-12 17:50:54 +0200974 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100976 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
977 char *name;
978 int len;
979
980 if (global.log_send_hostname != NULL) {
981 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT;
983 goto out;
984 }
985
986 if (*(args[1]))
987 name = args[1];
988 else
989 name = hostname;
990
991 len = strlen(name);
992
993 /* We'll add a space after the name to respect the log format */
994 free(global.log_send_hostname);
995 global.log_send_hostname = malloc(len + 2);
996 snprintf(global.log_send_hostname, len + 2, "%s ", name);
997 }
Kevinm48936af2010-12-22 16:08:21 +0000998 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 free(global.log_tag);
1005 global.log_tag = strdup(args[1]);
1006 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001007 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1008 if (global.spread_checks != 0) {
1009 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 err_code |= ERR_ALERT;
1011 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001012 }
1013 if (*(args[1]) == 0) {
1014 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001017 }
1018 global.spread_checks = atol(args[1]);
1019 if (global.spread_checks < 0 || global.spread_checks > 50) {
1020 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001021 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023 }
1024 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025 struct cfg_kw_list *kwl;
1026 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001027 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001028
1029 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1030 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1031 if (kwl->kw[index].section != CFG_GLOBAL)
1032 continue;
1033 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1034 /* prepare error message just in case */
1035 snprintf(trash, sizeof(trash),
1036 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001037 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001038 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001039 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001042 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001043 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_WARN;
1045 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001048 }
1049 }
1050 }
1051
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001055
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001057 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059}
1060
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001061void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001063 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 defproxy.mode = PR_MODE_TCP;
1065 defproxy.state = PR_STNEW;
1066 defproxy.maxconn = cfg_maxpconn;
1067 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001068
1069 defproxy.defsrv.inter = DEF_CHKINTR;
1070 defproxy.defsrv.fastinter = 0;
1071 defproxy.defsrv.downinter = 0;
1072 defproxy.defsrv.rise = DEF_RISETIME;
1073 defproxy.defsrv.fall = DEF_FALLTIME;
1074 defproxy.defsrv.check_port = 0;
1075 defproxy.defsrv.maxqueue = 0;
1076 defproxy.defsrv.minconn = 0;
1077 defproxy.defsrv.maxconn = 0;
1078 defproxy.defsrv.slowstart = 0;
1079 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1080 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1081 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082}
1083
Willy Tarreauade5ec42010-01-28 19:33:49 +01001084
1085static int create_cond_regex_rule(const char *file, int line,
1086 struct proxy *px, int dir, int action, int flags,
1087 const char *cmd, const char *reg, const char *repl,
1088 const char **cond_start)
1089{
1090 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001091 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001092 const char *err;
1093 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001094 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001095
1096 if (px == &defproxy) {
1097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto err;
1100 }
1101
1102 if (*reg == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto err;
1106 }
1107
1108 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1109 err_code |= ERR_WARN;
1110
Willy Tarreau5321c422010-01-28 20:35:13 +01001111 if (cond_start &&
1112 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001113 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1114 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1115 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001116 err_code |= ERR_ALERT | ERR_FATAL;
1117 goto err;
1118 }
1119 }
1120 else if (cond_start && **cond_start) {
1121 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1122 file, line, cmd, *cond_start);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001127 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001128 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001129 else
1130 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001131
Willy Tarreauade5ec42010-01-28 19:33:49 +01001132 preg = calloc(1, sizeof(regex_t));
1133 if (!preg) {
1134 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1135 err_code = ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138
1139 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1140 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1141 err_code = ERR_ALERT | ERR_FATAL;
1142 goto err;
1143 }
1144
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001145 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001146 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001147 if (repl && err) {
1148 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1149 file, line, cmd, *err);
1150 err_code |= ERR_ALERT | ERR_FATAL;
1151 goto err;
1152 }
1153
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001154 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001155 err_code |= ERR_WARN;
1156
Willy Tarreauf4068b62012-05-08 17:37:49 +02001157 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001158 return err_code;
1159 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001160 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001161 free(preg);
1162 return err_code;
1163}
1164
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001166 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001167 * Returns the error code, 0 if OK, or any combination of :
1168 * - ERR_ABORT: must abort ASAP
1169 * - ERR_FATAL: we can continue parsing but not start the service
1170 * - ERR_WARN: a warning has been emitted
1171 * - ERR_ALERT: an alert has been emitted
1172 * Only the two first ones can stop processing, the two others are just
1173 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001175int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1176{
1177 static struct peers *curpeers = NULL;
1178 struct peer *newpeer = NULL;
1179 const char *err;
1180 int err_code = 0;
1181
1182 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1183
1184 err = invalid_char(args[1]);
1185 if (err) {
1186 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1187 file, linenum, *err, args[0], args[1]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 }
1190
1191 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1192 /*
1193 * If there are two proxies with the same name only following
1194 * combinations are allowed:
1195 */
1196 if (strcmp(curpeers->id, args[1]) == 0) {
1197 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1198 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1199 err_code |= ERR_WARN;
1200 }
1201 }
1202
1203 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1205 err_code |= ERR_ALERT | ERR_ABORT;
1206 goto out;
1207 }
1208
1209 curpeers->next = peers;
1210 peers = curpeers;
1211 curpeers->conf.file = file;
1212 curpeers->conf.line = linenum;
1213 curpeers->last_change = now.tv_sec;
1214 curpeers->id = strdup(args[1]);
1215 }
1216 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1217 char *rport, *raddr;
1218 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001219 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001220
1221 if (!*args[2]) {
1222 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1223 file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227
1228 err = invalid_char(args[1]);
1229 if (err) {
1230 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1231 file, linenum, *err, args[1]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1237 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1238 err_code |= ERR_ALERT | ERR_ABORT;
1239 goto out;
1240 }
1241
1242 /* the peers are linked backwards first */
1243 curpeers->count++;
1244 newpeer->next = curpeers->remote;
1245 curpeers->remote = newpeer;
1246 newpeer->peers = curpeers;
1247 newpeer->conf.file = file;
1248 newpeer->conf.line = linenum;
1249
1250 newpeer->last_change = now.tv_sec;
1251 newpeer->id = strdup(args[1]);
1252
1253 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001254 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001255 if (rport) {
1256 *rport++ = 0;
1257 realport = atol(rport);
1258 }
1259 if (!realport) {
1260 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
1263 }
1264
Willy Tarreaufab5a432011-03-04 15:31:53 +01001265 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001266 free(raddr);
1267 if (!sk) {
1268 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001273 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02001274 newpeer->sock = &sock_raw;
1275 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001276
1277 if (!sk) {
1278 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1279 file, linenum, newpeer->addr.ss_family, args[2]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001284 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001285
1286 if (strcmp(newpeer->id, localpeer) == 0) {
1287 /* Current is local peer, it define a frontend */
1288 newpeer->local = 1;
1289
1290 if (!curpeers->peers_fe) {
1291 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1292 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1293 err_code |= ERR_ALERT | ERR_ABORT;
1294 goto out;
1295 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001296
Willy Tarreau237250c2011-07-29 01:49:03 +02001297 init_new_proxy(curpeers->peers_fe);
1298 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001299
1300 curpeers->peers_fe->last_change = now.tv_sec;
1301 curpeers->peers_fe->id = strdup(args[1]);
1302 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001303 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001304 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1305 curpeers->peers_fe->timeout.connect = 5000;
1306 curpeers->peers_fe->accept = peer_accept;
1307 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001308 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001309 err_code |= ERR_FATAL;
1310 goto out;
1311 }
1312 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1313 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1314 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1315 curpeers->peers_fe->listen->accept = session_accept;
1316 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1317 curpeers->peers_fe->listen->handler = process_session;
1318 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001319 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1320 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001321 }
1322 }
1323 } /* neither "peer" nor "peers" */
1324 else if (*args[0] != 0) {
1325 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1326 err_code |= ERR_ALERT | ERR_FATAL;
1327 goto out;
1328 }
1329
1330out:
1331 return err_code;
1332}
1333
1334
Willy Tarreau3842f002009-06-14 11:39:52 +02001335int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336{
1337 static struct proxy *curproxy = NULL;
1338 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001339 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001340 int rc;
1341 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001342 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001343 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001344 struct logsrv *tmplogsrv;
1345 struct logformat_node *tmplf;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001346 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347
Willy Tarreau977b8e42006-12-29 14:19:17 +01001348 if (!strcmp(args[0], "listen"))
1349 rc = PR_CAP_LISTEN;
1350 else if (!strcmp(args[0], "frontend"))
1351 rc = PR_CAP_FE | PR_CAP_RS;
1352 else if (!strcmp(args[0], "backend"))
1353 rc = PR_CAP_BE | PR_CAP_RS;
1354 else if (!strcmp(args[0], "ruleset"))
1355 rc = PR_CAP_RS;
1356 else
1357 rc = PR_CAP_NONE;
1358
1359 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 if (!*args[1]) {
1361 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1362 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1363 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001364 err_code |= ERR_ALERT | ERR_ABORT;
1365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001367
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001368 err = invalid_char(args[1]);
1369 if (err) {
1370 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1371 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001372 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001373 }
1374
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001375 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1376 /*
1377 * If there are two proxies with the same name only following
1378 * combinations are allowed:
1379 *
1380 * listen backend frontend ruleset
1381 * listen - - - -
1382 * backend - - OK -
1383 * frontend - OK - -
1384 * ruleset - - - -
1385 */
1386
1387 if (!strcmp(curproxy->id, args[1]) &&
1388 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1389 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001390 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1391 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1392 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001393 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001394 }
1395 }
1396
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1398 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001399 err_code |= ERR_ALERT | ERR_ABORT;
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001402
Willy Tarreau97cb7802010-01-03 20:23:58 +01001403 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 curproxy->next = proxy;
1405 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001406 curproxy->conf.file = file;
1407 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001408 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411
1412 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001414 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001415 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001416 err_code |= ERR_FATAL;
1417 goto out;
1418 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001419 new = curproxy->listen;
1420 while (new != last) {
1421 new->conf.file = file;
1422 new->conf.line = linenum;
1423 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001424 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
1427
1428 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001429 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001430 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001431
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001434 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001435 curproxy->no_options = defproxy.no_options;
1436 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001437 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001438 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001439 curproxy->except_net = defproxy.except_net;
1440 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001441 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001442 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001443
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001444 if (defproxy.fwdfor_hdr_len) {
1445 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1446 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1447 }
1448
Willy Tarreaub86db342009-11-30 11:50:16 +01001449 if (defproxy.orgto_hdr_len) {
1450 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1451 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1452 }
1453
Mark Lamourinec2247f02012-01-04 13:02:01 -05001454 if (defproxy.server_id_hdr_len) {
1455 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1456 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1457 }
1458
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459 if (curproxy->cap & PR_CAP_FE) {
1460 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001461 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001462 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463
1464 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001465 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1466 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467
1468 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 if (curproxy->cap & PR_CAP_BE) {
1472 curproxy->fullconn = defproxy.fullconn;
1473 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001475 if (defproxy.check_req) {
1476 curproxy->check_req = calloc(1, defproxy.check_len);
1477 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1478 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001481 if (defproxy.expect_str) {
1482 curproxy->expect_str = strdup(defproxy.expect_str);
1483 if (defproxy.expect_regex) {
1484 /* note: this regex is known to be valid */
1485 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1486 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1487 }
1488 }
1489
Willy Tarreau977b8e42006-12-29 14:19:17 +01001490 if (defproxy.cookie_name)
1491 curproxy->cookie_name = strdup(defproxy.cookie_name);
1492 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001493 if (defproxy.cookie_domain)
1494 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001495
Willy Tarreau31936852010-10-06 16:59:56 +02001496 if (defproxy.cookie_maxidle)
1497 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1498
1499 if (defproxy.cookie_maxlife)
1500 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1501
Emeric Brun647caf12009-06-30 17:57:00 +02001502 if (defproxy.rdp_cookie_name)
1503 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1504 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1505
Willy Tarreau01732802007-11-01 22:48:15 +01001506 if (defproxy.url_param_name)
1507 curproxy->url_param_name = strdup(defproxy.url_param_name);
1508 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001509
Benoitaffb4812009-03-25 13:02:10 +01001510 if (defproxy.hh_name)
1511 curproxy->hh_name = strdup(defproxy.hh_name);
1512 curproxy->hh_len = defproxy.hh_len;
1513 curproxy->hh_match_domain = defproxy.hh_match_domain;
1514
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001515 if (defproxy.iface_name)
1516 curproxy->iface_name = strdup(defproxy.iface_name);
1517 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001520 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001521 if (defproxy.capture_name)
1522 curproxy->capture_name = strdup(defproxy.capture_name);
1523 curproxy->capture_namelen = defproxy.capture_namelen;
1524 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526
Willy Tarreau977b8e42006-12-29 14:19:17 +01001527 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001528 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001529 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001530 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001531 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 curproxy->uri_auth = defproxy.uri_auth;
1533 curproxy->mon_net = defproxy.mon_net;
1534 curproxy->mon_mask = defproxy.mon_mask;
1535 if (defproxy.monitor_uri)
1536 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1537 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001538 if (defproxy.defbe.name)
1539 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 }
1541
1542 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001543 curproxy->timeout.connect = defproxy.timeout.connect;
1544 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001545 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001546 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001547 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001548 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001549 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001550 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001551 curproxy->source_addr = defproxy.source_addr;
1552 }
1553
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001555
1556 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001557 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001558 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001559 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001560 LIST_INIT(&node->list);
1561 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1562 }
1563
William Lallemand723b73a2012-02-08 16:37:49 +01001564 /* copy default log_format to curproxy */
1565 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1566 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1567 memcpy(node, tmplf, sizeof(struct logformat_node));
1568 LIST_INIT(&node->list);
1569 LIST_ADDQ(&curproxy->logformat, &node->list);
1570 }
1571
William Lallemanda73203e2012-03-12 12:48:57 +01001572 /* copy default unique_id to curproxy */
1573 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1574 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1575 memcpy(node, tmplf, sizeof(struct logformat_node));
1576 LIST_INIT(&node->list);
1577 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1578 }
1579
1580 /* copy default header unique id */
1581 if (defproxy.header_unique_id)
1582 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001585 curproxy->conf.used_listener_id = EB_ROOT;
1586 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001587
Willy Tarreau93893792009-07-23 13:19:11 +02001588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 }
1590 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1591 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001592 /* FIXME-20070101: we should do this too at the end of the
1593 * config parsing to free all default values.
1594 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001595 free(defproxy.check_req);
1596 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001597 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001598 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001600 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001601 free(defproxy.capture_name);
1602 free(defproxy.monitor_uri);
1603 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001604 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001605 free(defproxy.fwdfor_hdr_name);
1606 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001607 free(defproxy.orgto_hdr_name);
1608 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001609 free(defproxy.server_id_hdr_name);
1610 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001611 free(defproxy.expect_str);
1612 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001613
Willy Tarreaua534fea2008-08-03 12:19:50 +02001614 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001615 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001616
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 /* we cannot free uri_auth because it might already be used */
1618 init_default_instance();
1619 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001620 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 else if (curproxy == NULL) {
1624 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001627 }
1628
Willy Tarreau977b8e42006-12-29 14:19:17 +01001629
1630 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001632 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001633 int cur_arg;
1634
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 if (curproxy == &defproxy) {
1636 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001640 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642
Emeric Bruned760922010-10-22 17:59:25 +02001643 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001644 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_ALERT | ERR_FATAL;
1647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001649
1650 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001651
1652 /* NOTE: the following line might create several listeners if there
1653 * are comma-separated IPs or port ranges. So all further processing
1654 * will have to be applied to all listeners created after last_listen.
1655 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001656 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001660
Willy Tarreau90a570f2009-10-04 20:54:54 +02001661 new_listen = curproxy->listen;
1662 while (new_listen != last_listen) {
1663 new_listen->conf.file = file;
1664 new_listen->conf.line = linenum;
1665 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001666 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001667 }
1668
Emeric Bruned760922010-10-22 17:59:25 +02001669 /* Set default global rights and owner for unix bind */
1670 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1671 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1672 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001673 cur_arg = 2;
1674 while (*(args[cur_arg])) {
1675 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1676#ifdef SO_BINDTODEVICE
1677 struct listener *l;
1678
Emeric Bruned760922010-10-22 17:59:25 +02001679 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1680 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1681 file, linenum, args[0], args[cur_arg]);
1682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
1684 }
1685
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001686 if (!*args[cur_arg + 1]) {
1687 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001691 }
1692
1693 for (l = curproxy->listen; l != last_listen; l = l->next)
1694 l->interface = strdup(args[cur_arg + 1]);
1695
1696 global.last_checks |= LSTCHK_NETADM;
1697
1698 cur_arg += 2;
1699 continue;
1700#else
1701 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1702 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001705#endif
1706 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001707 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1708#ifdef TCP_MAXSEG
1709 struct listener *l;
1710 int mss;
1711
Emeric Bruned760922010-10-22 17:59:25 +02001712 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1713 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1714 file, linenum, args[0], args[cur_arg]);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
Willy Tarreaube1b9182009-06-14 18:48:19 +02001719 if (!*args[cur_arg + 1]) {
1720 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1721 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001724 }
1725
Willy Tarreau48a7e722010-12-24 15:26:39 +01001726 mss = atoi(args[cur_arg + 1]);
1727 if (!mss || abs(mss) > 65535) {
1728 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001732 }
1733
1734 for (l = curproxy->listen; l != last_listen; l = l->next)
1735 l->maxseg = mss;
1736
1737 cur_arg += 2;
1738 continue;
1739#else
1740 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1741 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001744#endif
1745 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001746
1747 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1748#ifdef TCP_DEFER_ACCEPT
1749 struct listener *l;
1750
1751 for (l = curproxy->listen; l != last_listen; l = l->next)
1752 l->options |= LI_O_DEF_ACCEPT;
1753
1754 cur_arg ++;
1755 continue;
1756#else
1757 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1758 file, linenum, args[0], args[cur_arg]);
1759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761#endif
1762 }
1763
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001764 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001765#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001766 struct listener *l;
1767
Emeric Bruned760922010-10-22 17:59:25 +02001768 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1769 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1770 file, linenum, args[0], args[cur_arg]);
1771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
1773 }
1774
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001775 for (l = curproxy->listen; l != last_listen; l = l->next)
1776 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001777
1778 cur_arg ++;
1779 continue;
1780#else
1781 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1782 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001785#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001786 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001787
Willy Tarreau8a956912010-10-15 14:27:08 +02001788 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1789 struct listener *l;
1790
1791 for (l = curproxy->listen; l != last_listen; l = l->next)
1792 l->options |= LI_O_ACC_PROXY;
1793
1794 cur_arg ++;
1795 continue;
1796 }
1797
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798 if (!strcmp(args[cur_arg], "name")) {
1799 struct listener *l;
1800
1801 for (l = curproxy->listen; l != last_listen; l = l->next)
1802 l->name = strdup(args[cur_arg + 1]);
1803
1804 cur_arg += 2;
1805 continue;
1806 }
1807
1808 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001809 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001810 struct listener *l;
1811
1812 if (curproxy->listen->next != last_listen) {
1813 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1814 file, linenum, args[cur_arg]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818
1819 if (!*args[cur_arg + 1]) {
1820 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1821 file, linenum, args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001827 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001828
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001829 if (curproxy->listen->luid <= 0) {
1830 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001831 file, linenum);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001836 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1837 if (node) {
1838 l = container_of(node, struct listener, conf.id);
1839 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1840 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
1843 }
1844 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1845
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001846 cur_arg += 2;
1847 continue;
1848 }
1849
Emeric Bruned760922010-10-22 17:59:25 +02001850 if (!strcmp(args[cur_arg], "mode")) {
1851
1852 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1853 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1854 file, linenum, args[0], args[cur_arg]);
1855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
1859 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1860
1861 cur_arg += 2;
1862 continue;
1863 }
1864
1865 if (!strcmp(args[cur_arg], "uid")) {
1866
1867 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1868 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1869 file, linenum, args[0], args[cur_arg]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872 }
1873
1874 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1875 cur_arg += 2;
1876 continue;
1877 }
1878
1879 if (!strcmp(args[cur_arg], "gid")) {
1880
1881 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1882 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1883 file, linenum, args[0], args[cur_arg]);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1889 cur_arg += 2;
1890 continue;
1891 }
1892
1893 if (!strcmp(args[cur_arg], "user")) {
1894 struct passwd *user;
1895
1896 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1897 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1898 file, linenum, args[0], args[cur_arg]);
1899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
1901 }
1902 user = getpwnam(args[cur_arg + 1]);
1903 if (!user) {
1904 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1905 file, linenum, args[0], args[cur_arg + 1 ]);
1906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
1908 }
1909
1910 curproxy->listen->perm.ux.uid = user->pw_uid;
1911 cur_arg += 2;
1912 continue;
1913 }
1914
1915 if (!strcmp(args[cur_arg], "group")) {
1916 struct group *group;
1917
1918 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1919 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1920 file, linenum, args[0], args[cur_arg]);
1921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
1923 }
1924 group = getgrnam(args[cur_arg + 1]);
1925 if (!group) {
1926 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1927 file, linenum, args[0], args[cur_arg + 1 ]);
1928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
1931
1932 curproxy->listen->perm.ux.gid = group->gr_gid;
1933 cur_arg += 2;
1934 continue;
1935 }
1936
Willy Tarreaub48f9582011-09-05 01:17:06 +02001937 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 +01001938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001941 }
Willy Tarreau93893792009-07-23 13:19:11 +02001942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
1944 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1945 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1946 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001953
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 /* flush useless bits */
1955 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001958 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001961
Willy Tarreau1c47f852006-07-09 08:22:27 +02001962 if (!*args[1]) {
1963 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1964 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001967 }
1968
Willy Tarreaua534fea2008-08-03 12:19:50 +02001969 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001970 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001971 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001972 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001973 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1974
Willy Tarreau93893792009-07-23 13:19:11 +02001975 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1978 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1979 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1980 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1981 else {
1982 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 }
1986 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001987 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001988 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001989
1990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1992 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001995 }
1996
1997 if (!*args[1]) {
1998 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002002 }
2003
2004 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002005 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002006
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002007 if (curproxy->uuid <= 0) {
2008 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002009 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002012 }
2013
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002014 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2015 if (node) {
2016 struct proxy *target = container_of(node, struct proxy, conf.id);
2017 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2018 file, linenum, proxy_type_str(curproxy), curproxy->id,
2019 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
2022 }
2023 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002024 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002025 else if (!strcmp(args[0], "description")) {
2026 int i, len=0;
2027 char *d;
2028
Cyril Bonté99ed3272010-01-24 23:29:44 +01002029 if (curproxy == &defproxy) {
2030 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2031 file, linenum, args[0]);
2032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
2034 }
2035
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002036 if (!*args[1]) {
2037 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2038 file, linenum, args[0]);
2039 return -1;
2040 }
2041
2042 for(i=1; *args[i]; i++)
2043 len += strlen(args[i])+1;
2044
2045 d = (char *)calloc(1, len);
2046 curproxy->desc = d;
2047
2048 d += sprintf(d, "%s", args[1]);
2049 for(i=2; *args[i]; i++)
2050 d += sprintf(d, " %s", args[i]);
2051
2052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2054 curproxy->state = PR_STSTOPPED;
2055 }
2056 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2057 curproxy->state = PR_STNEW;
2058 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002059 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2060 int cur_arg = 1;
2061 unsigned int set = 0;
2062
2063 while (*args[cur_arg]) {
2064 int u;
2065 if (strcmp(args[cur_arg], "all") == 0) {
2066 set = 0;
2067 break;
2068 }
2069 else if (strcmp(args[cur_arg], "odd") == 0) {
2070 set |= 0x55555555;
2071 }
2072 else if (strcmp(args[cur_arg], "even") == 0) {
2073 set |= 0xAAAAAAAA;
2074 }
2075 else {
2076 u = str2uic(args[cur_arg]);
2077 if (u < 1 || u > 32) {
2078 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002082 }
2083 if (u > global.nbproc) {
2084 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002087 }
2088 set |= 1 << (u - 1);
2089 }
2090 cur_arg++;
2091 }
2092 curproxy->bind_proc = set;
2093 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002094 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002095 if (curproxy == &defproxy) {
2096 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002099 }
2100
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002101 err = invalid_char(args[1]);
2102 if (err) {
2103 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2104 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002106 }
2107
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002108 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2109 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2110 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002113 }
2114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2116 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 if (*(args[1]) == 0) {
2122 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002124 err_code |= ERR_ALERT | ERR_FATAL;
2125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002127
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002128 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002129 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002130 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002131 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002132 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 curproxy->cookie_name = strdup(args[1]);
2134 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002135
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 cur_arg = 2;
2137 while (*(args[cur_arg])) {
2138 if (!strcmp(args[cur_arg], "rewrite")) {
2139 curproxy->options |= PR_O_COOK_RW;
2140 }
2141 else if (!strcmp(args[cur_arg], "indirect")) {
2142 curproxy->options |= PR_O_COOK_IND;
2143 }
2144 else if (!strcmp(args[cur_arg], "insert")) {
2145 curproxy->options |= PR_O_COOK_INS;
2146 }
2147 else if (!strcmp(args[cur_arg], "nocache")) {
2148 curproxy->options |= PR_O_COOK_NOC;
2149 }
2150 else if (!strcmp(args[cur_arg], "postonly")) {
2151 curproxy->options |= PR_O_COOK_POST;
2152 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002153 else if (!strcmp(args[cur_arg], "preserve")) {
2154 curproxy->options2 |= PR_O2_COOK_PSV;
2155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 else if (!strcmp(args[cur_arg], "prefix")) {
2157 curproxy->options |= PR_O_COOK_PFX;
2158 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002159 else if (!strcmp(args[cur_arg], "domain")) {
2160 if (!*args[cur_arg + 1]) {
2161 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2162 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002165 }
2166
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002167 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002168 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002169 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2170 " dots nor does not start with a dot."
2171 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002172 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002173 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002174 }
2175
2176 err = invalid_domainchar(args[cur_arg + 1]);
2177 if (err) {
2178 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2179 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002182 }
2183
Willy Tarreau68a897b2009-12-03 23:28:34 +01002184 if (!curproxy->cookie_domain) {
2185 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2186 } else {
2187 /* one domain was already specified, add another one by
2188 * building the string which will be returned along with
2189 * the cookie.
2190 */
2191 char *new_ptr;
2192 int new_len = strlen(curproxy->cookie_domain) +
2193 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2194 new_ptr = malloc(new_len);
2195 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2196 free(curproxy->cookie_domain);
2197 curproxy->cookie_domain = new_ptr;
2198 }
Willy Tarreau31936852010-10-06 16:59:56 +02002199 cur_arg++;
2200 }
2201 else if (!strcmp(args[cur_arg], "maxidle")) {
2202 unsigned int maxidle;
2203 const char *res;
2204
2205 if (!*args[cur_arg + 1]) {
2206 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2207 file, linenum, args[cur_arg]);
2208 err_code |= ERR_ALERT | ERR_FATAL;
2209 goto out;
2210 }
2211
2212 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2213 if (res) {
2214 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2215 file, linenum, *res, args[cur_arg]);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
2218 }
2219 curproxy->cookie_maxidle = maxidle;
2220 cur_arg++;
2221 }
2222 else if (!strcmp(args[cur_arg], "maxlife")) {
2223 unsigned int maxlife;
2224 const char *res;
2225
2226 if (!*args[cur_arg + 1]) {
2227 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2228 file, linenum, args[cur_arg]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232
2233 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2234 if (res) {
2235 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2236 file, linenum, *res, args[cur_arg]);
2237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
2239 }
2240 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002241 cur_arg++;
2242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002244 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 +02002245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 cur_arg++;
2250 }
2251 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2252 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2253 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 }
2256
2257 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2258 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2259 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002262
2263 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2264 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2265 file, linenum);
2266 err_code |= ERR_ALERT | ERR_FATAL;
2267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002269 else if (!strcmp(args[0], "persist")) { /* persist */
2270 if (*(args[1]) == 0) {
2271 Alert("parsing [%s:%d] : missing persist method.\n",
2272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002275 }
2276
2277 if (!strncmp(args[1], "rdp-cookie", 10)) {
2278 curproxy->options2 |= PR_O2_RDPC_PRST;
2279
Emeric Brunb982a3d2010-01-04 15:45:53 +01002280 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002281 const char *beg, *end;
2282
2283 beg = args[1] + 11;
2284 end = strchr(beg, ')');
2285
2286 if (!end || end == beg) {
2287 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2288 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002291 }
2292
2293 free(curproxy->rdp_cookie_name);
2294 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2295 curproxy->rdp_cookie_len = end-beg;
2296 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002297 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002298 free(curproxy->rdp_cookie_name);
2299 curproxy->rdp_cookie_name = strdup("msts");
2300 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2301 }
2302 else { /* syntax */
2303 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2304 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002307 }
2308 }
2309 else {
2310 Alert("parsing [%s:%d] : unknown persist method.\n",
2311 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002314 }
2315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002317 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002319 if (curproxy == &defproxy) {
2320 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
Willy Tarreau977b8e42006-12-29 14:19:17 +01002325 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 }
2334 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002335 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 curproxy->appsession_name = strdup(args[1]);
2337 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2338 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002339 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2340 if (err) {
2341 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2342 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002345 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002346 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002347
Willy Tarreau51041c72007-09-09 21:56:53 +02002348 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2349 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_ALERT | ERR_ABORT;
2351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002353
2354 cur_arg = 6;
2355 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002356 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2357 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002358 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002359 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002360 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002361 } else if (!strcmp(args[cur_arg], "prefix")) {
2362 curproxy->options2 |= PR_O2_AS_PFX;
2363 } else if (!strcmp(args[cur_arg], "mode")) {
2364 if (!*args[cur_arg + 1]) {
2365 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2366 file, linenum, args[0], args[cur_arg]);
2367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
2369 }
2370
2371 cur_arg++;
2372 if (!strcmp(args[cur_arg], "query-string")) {
2373 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2374 curproxy->options2 |= PR_O2_AS_M_QS;
2375 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2376 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2377 curproxy->options2 |= PR_O2_AS_M_PP;
2378 } else {
2379 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002384 cur_arg++;
2385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 } /* Url App Session */
2387 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002388 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002392 if (curproxy == &defproxy) {
2393 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
2396 }
2397
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 if (*(args[4]) == 0) {
2399 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002404 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 curproxy->capture_name = strdup(args[2]);
2406 curproxy->capture_namelen = strlen(curproxy->capture_name);
2407 curproxy->capture_len = atol(args[4]);
2408 if (curproxy->capture_len >= CAPTURE_LEN) {
2409 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2410 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 curproxy->capture_len = CAPTURE_LEN - 1;
2413 }
2414 curproxy->to_log |= LW_COOKIE;
2415 }
2416 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2417 struct cap_hdr *hdr;
2418
2419 if (curproxy == &defproxy) {
2420 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 +02002421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 }
2424
2425 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2426 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2427 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431
2432 hdr = calloc(sizeof(struct cap_hdr), 1);
2433 hdr->next = curproxy->req_cap;
2434 hdr->name = strdup(args[3]);
2435 hdr->namelen = strlen(args[3]);
2436 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002437 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 hdr->index = curproxy->nb_req_cap++;
2439 curproxy->req_cap = hdr;
2440 curproxy->to_log |= LW_REQHDR;
2441 }
2442 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2443 struct cap_hdr *hdr;
2444
2445 if (curproxy == &defproxy) {
2446 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 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
2450
2451 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2452 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2453 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 }
2457 hdr = calloc(sizeof(struct cap_hdr), 1);
2458 hdr->next = curproxy->rsp_cap;
2459 hdr->name = strdup(args[3]);
2460 hdr->namelen = strlen(args[3]);
2461 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002462 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 hdr->index = curproxy->nb_rsp_cap++;
2464 curproxy->rsp_cap = hdr;
2465 curproxy->to_log |= LW_RSPHDR;
2466 }
2467 else {
2468 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2469 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }
2473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002475 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002477
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 if (*(args[1]) == 0) {
2479 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2480 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 }
2484 curproxy->conn_retries = atol(args[1]);
2485 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002486 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002487 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002488
2489 if (curproxy == &defproxy) {
2490 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494
Willy Tarreauff011f22011-01-06 17:51:27 +01002495 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 +01002496 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2497 file, linenum, args[0]);
2498 err_code |= ERR_WARN;
2499 }
2500
Willy Tarreauff011f22011-01-06 17:51:27 +01002501 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002502
Willy Tarreauff011f22011-01-06 17:51:27 +01002503 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002504 err_code |= ERR_ALERT | ERR_ABORT;
2505 goto out;
2506 }
2507
Willy Tarreauff011f22011-01-06 17:51:27 +01002508 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2509 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002510 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002511 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2512 /* set the header name and length into the proxy structure */
2513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2514 err_code |= ERR_WARN;
2515
2516 if (!*args[1]) {
2517 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2518 file, linenum, args[0]);
2519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
2521 }
2522
2523 /* set the desired header name */
2524 free(curproxy->server_id_hdr_name);
2525 curproxy->server_id_hdr_name = strdup(args[1]);
2526 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2527 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002528 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002529 if (curproxy == &defproxy) {
2530 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002533 }
2534
Willy Tarreauef6494c2010-01-28 17:12:36 +01002535 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002536 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2537 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002540 }
2541
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002542 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2543 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2544 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002547 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002548
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002549 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002550 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002551 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002552 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002553 struct redirect_rule *rule;
2554 int cur_arg;
2555 int type = REDIRECT_TYPE_NONE;
2556 int code = 302;
2557 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002558 char *cookie = NULL;
2559 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002560 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002561
Cyril Bonté99ed3272010-01-24 23:29:44 +01002562 if (curproxy == &defproxy) {
2563 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
2566 }
2567
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002568 cur_arg = 1;
2569 while (*(args[cur_arg])) {
2570 if (!strcmp(args[cur_arg], "location")) {
2571 if (!*args[cur_arg + 1]) {
2572 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2573 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002576 }
2577
2578 type = REDIRECT_TYPE_LOCATION;
2579 cur_arg++;
2580 destination = args[cur_arg];
2581 }
2582 else if (!strcmp(args[cur_arg], "prefix")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2585 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 }
2589
2590 type = REDIRECT_TYPE_PREFIX;
2591 cur_arg++;
2592 destination = args[cur_arg];
2593 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 else if (!strcmp(args[cur_arg], "set-cookie")) {
2595 if (!*args[cur_arg + 1]) {
2596 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2597 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002600 }
2601
2602 cur_arg++;
2603 cookie = args[cur_arg];
2604 cookie_set = 1;
2605 }
2606 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2607 if (!*args[cur_arg + 1]) {
2608 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2609 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002612 }
2613
2614 cur_arg++;
2615 cookie = args[cur_arg];
2616 cookie_set = 0;
2617 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002618 else if (!strcmp(args[cur_arg],"code")) {
2619 if (!*args[cur_arg + 1]) {
2620 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2621 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002624 }
2625 cur_arg++;
2626 code = atol(args[cur_arg]);
2627 if (code < 301 || code > 303) {
2628 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2629 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002632 }
2633 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002634 else if (!strcmp(args[cur_arg],"drop-query")) {
2635 flags |= REDIRECT_FLAG_DROP_QS;
2636 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002637 else if (!strcmp(args[cur_arg],"append-slash")) {
2638 flags |= REDIRECT_FLAG_APPEND_SLASH;
2639 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002640 else if (strcmp(args[cur_arg], "if") == 0 ||
2641 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002642 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002644 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2645 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
2648 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 break;
2650 }
2651 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002652 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 +02002653 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002656 }
2657 cur_arg++;
2658 }
2659
2660 if (type == REDIRECT_TYPE_NONE) {
2661 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2662 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002665 }
2666
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002667 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2668 rule->cond = cond;
2669 rule->rdr_str = strdup(destination);
2670 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002671 if (cookie) {
2672 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002673 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002674 */
2675 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002676 if (cookie_set) {
2677 rule->cookie_str = malloc(rule->cookie_len + 10);
2678 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2679 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2680 rule->cookie_len += 9;
2681 } else {
2682 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002683 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002684 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2685 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002686 }
2687 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002688 rule->type = type;
2689 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002690 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002691 LIST_INIT(&rule->list);
2692 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002693 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2694 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002695 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002696 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002697 struct switching_rule *rule;
2698
Willy Tarreaub099aca2008-10-12 17:26:37 +02002699 if (curproxy == &defproxy) {
2700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002703 }
2704
Willy Tarreau55ea7572007-06-17 19:56:27 +02002705 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707
2708 if (*(args[1]) == 0) {
2709 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712 }
2713
Willy Tarreauef6494c2010-01-28 17:12:36 +01002714 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002715 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002719 }
2720
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002721 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2722 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2723 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002726 }
2727
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002728 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002729
Willy Tarreau55ea7572007-06-17 19:56:27 +02002730 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2731 rule->cond = cond;
2732 rule->be.name = strdup(args[1]);
2733 LIST_INIT(&rule->list);
2734 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2735 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002736 else if (strcmp(args[0], "use-server") == 0) {
2737 struct server_rule *rule;
2738
2739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744
2745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2746 err_code |= ERR_WARN;
2747
2748 if (*(args[1]) == 0) {
2749 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
2752 }
2753
2754 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2755 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2756 file, linenum, args[0]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002761 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2762 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2763 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
2766 }
2767
2768 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2769
2770 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2771 rule->cond = cond;
2772 rule->srv.name = strdup(args[1]);
2773 LIST_INIT(&rule->list);
2774 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2775 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2776 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002777 else if ((!strcmp(args[0], "force-persist")) ||
2778 (!strcmp(args[0], "ignore-persist"))) {
2779 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002780
2781 if (curproxy == &defproxy) {
2782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786
2787 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2788 err_code |= ERR_WARN;
2789
Willy Tarreauef6494c2010-01-28 17:12:36 +01002790 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002791 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2792 file, linenum, args[0]);
2793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
2795 }
2796
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002797 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2798 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2799 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
2802 }
2803
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002804 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002805
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002806 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002807 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002808 if (!strcmp(args[0], "force-persist")) {
2809 rule->type = PERSIST_TYPE_FORCE;
2810 } else {
2811 rule->type = PERSIST_TYPE_IGNORE;
2812 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002813 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002814 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002815 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002816 else if (!strcmp(args[0], "stick-table")) {
2817 int myidx = 1;
2818
Emeric Brun32da3c42010-09-23 18:39:19 +02002819 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 curproxy->table.type = (unsigned int)-1;
2821 while (*args[myidx]) {
2822 const char *err;
2823
2824 if (strcmp(args[myidx], "size") == 0) {
2825 myidx++;
2826 if (!*(args[myidx])) {
2827 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2828 file, linenum, args[myidx-1]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2833 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2834 file, linenum, *err, args[myidx-1]);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002838 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002839 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002840 else if (strcmp(args[myidx], "peers") == 0) {
2841 myidx++;
2842 if (!*(args[myidx])) {
2843 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2844 file, linenum, args[myidx-1]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 curproxy->table.peers.name = strdup(args[myidx++]);
2849 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002850 else if (strcmp(args[myidx], "expire") == 0) {
2851 myidx++;
2852 if (!*(args[myidx])) {
2853 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2854 file, linenum, args[myidx-1]);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2859 if (err) {
2860 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2861 file, linenum, *err, args[myidx-1]);
2862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
2864 }
2865 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002866 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
2868 else if (strcmp(args[myidx], "nopurge") == 0) {
2869 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002870 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002871 }
2872 else if (strcmp(args[myidx], "type") == 0) {
2873 myidx++;
2874 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2875 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2876 file, linenum, args[myidx]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002880 /* myidx already points to next arg */
2881 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002882 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002883 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002884 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002885
2886 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002887 nw = args[myidx];
2888 while (*nw) {
2889 /* the "store" keyword supports a comma-separated list */
2890 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002891 sa = NULL; /* store arg */
2892 while (*nw && *nw != ',') {
2893 if (*nw == '(') {
2894 *nw = 0;
2895 sa = ++nw;
2896 while (*nw != ')') {
2897 if (!*nw) {
2898 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2899 file, linenum, args[0], cw);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
2903 nw++;
2904 }
2905 *nw = '\0';
2906 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002907 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002908 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002909 if (*nw)
2910 *nw++ = '\0';
2911 type = stktable_get_data_type(cw);
2912 if (type < 0) {
2913 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2914 file, linenum, args[0], cw);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917 }
Willy Tarreauac782882010-06-20 10:41:54 +02002918
2919 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2920 switch (err) {
2921 case PE_NONE: break;
2922 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002923 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2924 file, linenum, args[0], cw);
2925 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002926 break;
2927
2928 case PE_ARG_MISSING:
2929 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2930 file, linenum, args[0], cw);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933
2934 case PE_ARG_NOT_USED:
2935 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2936 file, linenum, args[0], cw);
2937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
2939
2940 default:
2941 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2942 file, linenum, args[0], cw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002945 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002946 }
2947 myidx++;
2948 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002949 else {
2950 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2951 file, linenum, args[myidx]);
2952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002955 }
2956
2957 if (!curproxy->table.size) {
2958 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2959 file, linenum);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
2964 if (curproxy->table.type == (unsigned int)-1) {
2965 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2966 file, linenum);
2967 err_code |= ERR_ALERT | ERR_FATAL;
2968 goto out;
2969 }
2970 }
2971 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002973 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 int myidx = 0;
2975 const char *name = NULL;
2976 int flags;
2977
2978 if (curproxy == &defproxy) {
2979 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983
2984 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2985 err_code |= ERR_WARN;
2986 goto out;
2987 }
2988
2989 myidx++;
2990 if ((strcmp(args[myidx], "store") == 0) ||
2991 (strcmp(args[myidx], "store-request") == 0)) {
2992 myidx++;
2993 flags = STK_IS_STORE;
2994 }
2995 else if (strcmp(args[myidx], "store-response") == 0) {
2996 myidx++;
2997 flags = STK_IS_STORE | STK_ON_RSP;
2998 }
2999 else if (strcmp(args[myidx], "match") == 0) {
3000 myidx++;
3001 flags = STK_IS_MATCH;
3002 }
3003 else if (strcmp(args[myidx], "on") == 0) {
3004 myidx++;
3005 flags = STK_IS_MATCH | STK_IS_STORE;
3006 }
3007 else {
3008 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
3011 }
3012
3013 if (*(args[myidx]) == 0) {
3014 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
3017 }
3018
Willy Tarreau12785782012-04-27 21:37:17 +02003019 expr = sample_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003021 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003027 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3029 file, linenum, args[0], expr->fetch->kw);
3030 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003031 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 goto out;
3033 }
3034 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003035 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3037 file, linenum, args[0], expr->fetch->kw);
3038 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003039 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 goto out;
3041 }
3042 }
3043
3044 if (strcmp(args[myidx], "table") == 0) {
3045 myidx++;
3046 name = args[myidx++];
3047 }
3048
Willy Tarreauef6494c2010-01-28 17:12:36 +01003049 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003050 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3051 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3052 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003054 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 goto out;
3056 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003058 else if (*(args[myidx])) {
3059 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3060 file, linenum, args[0], args[myidx]);
3061 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003062 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003063 goto out;
3064 }
Emeric Brun97679e72010-09-23 17:56:44 +02003065 if (flags & STK_ON_RSP)
3066 err_code |= warnif_cond_requires_req(cond, file, linenum);
3067 else
3068 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003069
Emeric Brunb982a3d2010-01-04 15:45:53 +01003070 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3071 rule->cond = cond;
3072 rule->expr = expr;
3073 rule->flags = flags;
3074 rule->table.name = name ? strdup(name) : NULL;
3075 LIST_INIT(&rule->list);
3076 if (flags & STK_ON_RSP)
3077 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3078 else
3079 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003082 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003084
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3086 curproxy->uri_auth = NULL; /* we must detach from the default config */
3087
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003088 if (!*args[1]) {
3089 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003090 } else if (!strcmp(args[1], "admin")) {
3091 struct stats_admin_rule *rule;
3092
3093 if (curproxy == &defproxy) {
3094 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098
3099 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3100 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3101 err_code |= ERR_ALERT | ERR_ABORT;
3102 goto out;
3103 }
3104
3105 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3106 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3107 file, linenum, args[0], args[1]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003111 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3112 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3113 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
3118 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3119
3120 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3121 rule->cond = cond;
3122 LIST_INIT(&rule->list);
3123 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 } else if (!strcmp(args[1], "uri")) {
3125 if (*(args[2]) == 0) {
3126 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_ABORT;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
3134 } else if (!strcmp(args[1], "realm")) {
3135 if (*(args[2]) == 0) {
3136 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3140 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003144 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003145 unsigned interval;
3146
3147 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3148 if (err) {
3149 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3150 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003153 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3154 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_ABORT;
3156 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003157 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003158 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003159 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003160
3161 if (curproxy == &defproxy) {
3162 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165 }
3166
3167 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3168 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172
Willy Tarreauff011f22011-01-06 17:51:27 +01003173 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3174 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003175 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3176 file, linenum, args[0]);
3177 err_code |= ERR_WARN;
3178 }
3179
Willy Tarreauff011f22011-01-06 17:51:27 +01003180 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003181
Willy Tarreauff011f22011-01-06 17:51:27 +01003182 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003183 err_code |= ERR_ALERT | ERR_ABORT;
3184 goto out;
3185 }
3186
Willy Tarreauff011f22011-01-06 17:51:27 +01003187 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3188 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003189
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 } else if (!strcmp(args[1], "auth")) {
3191 if (*(args[2]) == 0) {
3192 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3196 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_ABORT;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 } else if (!strcmp(args[1], "scope")) {
3201 if (*(args[2]) == 0) {
3202 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3206 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_ABORT;
3208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 }
3210 } else if (!strcmp(args[1], "enable")) {
3211 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_ABORT;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003216 } else if (!strcmp(args[1], "hide-version")) {
3217 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3218 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_ABORT;
3220 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003221 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003222 } else if (!strcmp(args[1], "show-legends")) {
3223 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3224 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3225 err_code |= ERR_ALERT | ERR_ABORT;
3226 goto out;
3227 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003228 } else if (!strcmp(args[1], "show-node")) {
3229
3230 if (*args[2]) {
3231 int i;
3232 char c;
3233
3234 for (i=0; args[2][i]; i++) {
3235 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003236 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3237 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003238 break;
3239 }
3240
3241 if (!i || args[2][i]) {
3242 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3243 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3244 file, linenum, args[0], args[1]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 }
3249
3250 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3251 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3252 err_code |= ERR_ALERT | ERR_ABORT;
3253 goto out;
3254 }
3255 } else if (!strcmp(args[1], "show-desc")) {
3256 char *desc = NULL;
3257
3258 if (*args[2]) {
3259 int i, len=0;
3260 char *d;
3261
3262 for(i=2; *args[i]; i++)
3263 len += strlen(args[i])+1;
3264
3265 desc = d = (char *)calloc(1, len);
3266
3267 d += sprintf(d, "%s", args[2]);
3268 for(i=3; *args[i]; i++)
3269 d += sprintf(d, " %s", args[i]);
3270 }
3271
3272 if (!*args[2] && !global.desc)
3273 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3274 file, linenum, args[1]);
3275 else {
3276 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3277 free(desc);
3278 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3279 err_code |= ERR_ALERT | ERR_ABORT;
3280 goto out;
3281 }
3282 free(desc);
3283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003285stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003286 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 +01003287 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 }
3291 }
3292 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003293 int optnum;
3294
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003295 if (*(args[1]) == '\0') {
3296 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003301
3302 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3303 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003304 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3305 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3306 file, linenum, cfg_opts[optnum].name);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
Willy Tarreau93893792009-07-23 13:19:11 +02003310 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3311 err_code |= ERR_WARN;
3312 goto out;
3313 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003314
Willy Tarreau3842f002009-06-14 11:39:52 +02003315 curproxy->no_options &= ~cfg_opts[optnum].val;
3316 curproxy->options &= ~cfg_opts[optnum].val;
3317
3318 switch (kwm) {
3319 case KWM_STD:
3320 curproxy->options |= cfg_opts[optnum].val;
3321 break;
3322 case KWM_NO:
3323 curproxy->no_options |= cfg_opts[optnum].val;
3324 break;
3325 case KWM_DEF: /* already cleared */
3326 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003327 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003328
Willy Tarreau93893792009-07-23 13:19:11 +02003329 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003330 }
3331 }
3332
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003333 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3334 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003335 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3336 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3337 file, linenum, cfg_opts2[optnum].name);
3338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
3340 }
Willy Tarreau93893792009-07-23 13:19:11 +02003341 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3342 err_code |= ERR_WARN;
3343 goto out;
3344 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003345
Willy Tarreau3842f002009-06-14 11:39:52 +02003346 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3347 curproxy->options2 &= ~cfg_opts2[optnum].val;
3348
3349 switch (kwm) {
3350 case KWM_STD:
3351 curproxy->options2 |= cfg_opts2[optnum].val;
3352 break;
3353 case KWM_NO:
3354 curproxy->no_options2 |= cfg_opts2[optnum].val;
3355 break;
3356 case KWM_DEF: /* already cleared */
3357 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003358 }
Willy Tarreau93893792009-07-23 13:19:11 +02003359 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003360 }
3361 }
3362
Willy Tarreau3842f002009-06-14 11:39:52 +02003363 if (kwm != KWM_STD) {
3364 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003365 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003368 }
3369
Emeric Brun3a058f32009-06-30 18:26:00 +02003370 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003371 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003373 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003374 if (*(args[2]) != '\0') {
3375 if (!strcmp(args[2], "clf")) {
3376 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003377 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003378 } else {
3379 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003382 }
3383 }
William Lallemand1d705562012-03-12 12:46:41 +01003384 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003385 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003386 else if (!strcmp(args[1], "tcplog")) {
3387 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003389 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003390 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 else if (!strcmp(args[1], "tcpka")) {
3393 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003394 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003395 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396
3397 if (curproxy->cap & PR_CAP_FE)
3398 curproxy->options |= PR_O_TCP_CLI_KA;
3399 if (curproxy->cap & PR_CAP_BE)
3400 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
3402 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_WARN;
3405
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003407 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003408 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003409 curproxy->options2 &= ~PR_O2_CHK_ANY;
3410 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 if (!*args[2]) { /* no argument */
3412 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3413 curproxy->check_len = strlen(DEF_CHECK_REQ);
3414 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003415 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 curproxy->check_req = (char *)malloc(reqlen);
3417 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003418 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003420 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 if (*args[4])
3422 reqlen += strlen(args[4]);
3423 else
3424 reqlen += strlen("HTTP/1.0");
3425
3426 curproxy->check_req = (char *)malloc(reqlen);
3427 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003428 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003430 }
3431 else if (!strcmp(args[1], "ssl-hello-chk")) {
3432 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003434 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003435
Willy Tarreaua534fea2008-08-03 12:19:50 +02003436 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003437 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003438 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003439 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 }
Willy Tarreau23677902007-05-08 23:50:35 +02003441 else if (!strcmp(args[1], "smtpchk")) {
3442 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003443 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003444 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003445 curproxy->options2 &= ~PR_O2_CHK_ANY;
3446 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003447
3448 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3449 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3450 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3451 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3452 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3453 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3454 curproxy->check_req = (char *)malloc(reqlen);
3455 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3456 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3457 } else {
3458 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3459 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3460 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3461 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3462 }
3463 }
3464 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003465 else if (!strcmp(args[1], "pgsql-check")) {
3466 /* use PostgreSQL request to check servers' health */
3467 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3468 err_code |= ERR_WARN;
3469
3470 free(curproxy->check_req);
3471 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003472 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003473 curproxy->options2 |= PR_O2_PGSQL_CHK;
3474
3475 if (*(args[2])) {
3476 int cur_arg = 2;
3477
3478 while (*(args[cur_arg])) {
3479 if (strcmp(args[cur_arg], "user") == 0) {
3480 char * packet;
3481 uint32_t packet_len;
3482 uint32_t pv;
3483
3484 /* suboption header - needs additional argument for it */
3485 if (*(args[cur_arg+1]) == 0) {
3486 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3487 file, linenum, args[0], args[1], args[cur_arg]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491
3492 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3493 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3494 pv = htonl(0x30000); /* protocol version 3.0 */
3495
3496 packet = (char*) calloc(1, packet_len);
3497
3498 memcpy(packet + 4, &pv, 4);
3499
3500 /* copy "user" */
3501 memcpy(packet + 8, "user", 4);
3502
3503 /* copy username */
3504 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3505
3506 free(curproxy->check_req);
3507 curproxy->check_req = packet;
3508 curproxy->check_len = packet_len;
3509
3510 packet_len = htonl(packet_len);
3511 memcpy(packet, &packet_len, 4);
3512 cur_arg += 2;
3513 } else {
3514 /* unknown suboption - catchall */
3515 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3516 file, linenum, args[0], args[1]);
3517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
3519 }
3520 } /* end while loop */
3521 }
3522 }
3523
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003524 else if (!strcmp(args[1], "redis-check")) {
3525 /* use REDIS PING request to check servers' health */
3526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3527 err_code |= ERR_WARN;
3528
3529 free(curproxy->check_req);
3530 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003531 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003532 curproxy->options2 |= PR_O2_REDIS_CHK;
3533
3534 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3535 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3536 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3537 }
3538
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003539 else if (!strcmp(args[1], "mysql-check")) {
3540 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003541 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3542 err_code |= ERR_WARN;
3543
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003544 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003545 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003546 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003547 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003548
3549 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3550 * const char mysql40_client_auth_pkt[] = {
3551 * "\x0e\x00\x00" // packet length
3552 * "\x01" // packet number
3553 * "\x00\x00" // client capabilities
3554 * "\x00\x00\x01" // max packet
3555 * "haproxy\x00" // username (null terminated string)
3556 * "\x00" // filler (always 0x00)
3557 * "\x01\x00\x00" // packet length
3558 * "\x00" // packet number
3559 * "\x01" // COM_QUIT command
3560 * };
3561 */
3562
3563 if (*(args[2])) {
3564 int cur_arg = 2;
3565
3566 while (*(args[cur_arg])) {
3567 if (strcmp(args[cur_arg], "user") == 0) {
3568 char *mysqluser;
3569 int packetlen, reqlen, userlen;
3570
3571 /* suboption header - needs additional argument for it */
3572 if (*(args[cur_arg+1]) == 0) {
3573 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3574 file, linenum, args[0], args[1], args[cur_arg]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 mysqluser = args[cur_arg + 1];
3579 userlen = strlen(mysqluser);
3580 packetlen = userlen + 7;
3581 reqlen = packetlen + 9;
3582
3583 free(curproxy->check_req);
3584 curproxy->check_req = (char *)calloc(1, reqlen);
3585 curproxy->check_len = reqlen;
3586
3587 snprintf(curproxy->check_req, 4, "%c%c%c",
3588 ((unsigned char) packetlen & 0xff),
3589 ((unsigned char) (packetlen >> 8) & 0xff),
3590 ((unsigned char) (packetlen >> 16) & 0xff));
3591
3592 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003593 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003594 curproxy->check_req[8] = 1;
3595 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3596 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3597 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3598 cur_arg += 2;
3599 } else {
3600 /* unknown suboption - catchall */
3601 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3602 file, linenum, args[0], args[1]);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606 } /* end while loop */
3607 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003608 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003609 else if (!strcmp(args[1], "ldap-check")) {
3610 /* use LDAP request to check servers' health */
3611 free(curproxy->check_req);
3612 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003613 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003614 curproxy->options2 |= PR_O2_LDAP_CHK;
3615
3616 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3617 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3618 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3619 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003620 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003621 int cur_arg;
3622
3623 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3624 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003625 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003626
Willy Tarreau87cf5142011-08-19 22:57:24 +02003627 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003628
3629 free(curproxy->fwdfor_hdr_name);
3630 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3631 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3632
3633 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3634 cur_arg = 2;
3635 while (*(args[cur_arg])) {
3636 if (!strcmp(args[cur_arg], "except")) {
3637 /* suboption except - needs additional argument for it */
3638 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3639 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3640 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003643 }
3644 /* flush useless bits */
3645 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003646 cur_arg += 2;
3647 } else if (!strcmp(args[cur_arg], "header")) {
3648 /* suboption header - needs additional argument for it */
3649 if (*(args[cur_arg+1]) == 0) {
3650 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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;
Ross Westaf72a1d2008-08-03 10:51:45 +02003654 }
3655 free(curproxy->fwdfor_hdr_name);
3656 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3657 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3658 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003659 } else if (!strcmp(args[cur_arg], "if-none")) {
3660 curproxy->options &= ~PR_O_FF_ALWAYS;
3661 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003663 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003664 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003668 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003669 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003670 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003671 else if (!strcmp(args[1], "originalto")) {
3672 int cur_arg;
3673
3674 /* insert x-original-to field, but not for the IP address listed as an except.
3675 * set default options (ie: bitfield, header name, etc)
3676 */
3677
3678 curproxy->options |= PR_O_ORGTO;
3679
3680 free(curproxy->orgto_hdr_name);
3681 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3682 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3683
Willy Tarreau87cf5142011-08-19 22:57:24 +02003684 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003685 cur_arg = 2;
3686 while (*(args[cur_arg])) {
3687 if (!strcmp(args[cur_arg], "except")) {
3688 /* suboption except - needs additional argument for it */
3689 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3690 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3691 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003694 }
3695 /* flush useless bits */
3696 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3697 cur_arg += 2;
3698 } else if (!strcmp(args[cur_arg], "header")) {
3699 /* suboption header - needs additional argument for it */
3700 if (*(args[cur_arg+1]) == 0) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> 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 free(curproxy->orgto_hdr_name);
3707 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3708 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3709 cur_arg += 2;
3710 } else {
3711 /* unknown suboption - catchall */
3712 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3713 file, linenum, args[0], args[1]);
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 } /* end while loop */
3718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 else {
3720 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
Willy Tarreau93893792009-07-23 13:19:11 +02003724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003726 else if (!strcmp(args[0], "default_backend")) {
3727 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003729
3730 if (*(args[1]) == 0) {
3731 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003734 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003735 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003736 curproxy->defbe.name = strdup(args[1]);
3737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003741
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003742 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003745 /* enable reconnections to dispatch */
3746 curproxy->options |= PR_O_REDISP;
3747 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003748 else if (!strcmp(args[0], "http-check")) {
3749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003751
3752 if (strcmp(args[1], "disable-on-404") == 0) {
3753 /* enable a graceful server shutdown on an HTTP 404 response */
3754 curproxy->options |= PR_O_DISABLE404;
3755 }
Willy Tarreauef781042010-01-27 11:53:01 +01003756 else if (strcmp(args[1], "send-state") == 0) {
3757 /* enable emission of the apparent state of a server in HTTP checks */
3758 curproxy->options2 |= PR_O2_CHK_SNDST;
3759 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003760 else if (strcmp(args[1], "expect") == 0) {
3761 const char *ptr_arg;
3762 int cur_arg;
3763
3764 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3765 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769
3770 cur_arg = 2;
3771 /* consider exclamation marks, sole or at the beginning of a word */
3772 while (*(ptr_arg = args[cur_arg])) {
3773 while (*ptr_arg == '!') {
3774 curproxy->options2 ^= PR_O2_EXP_INV;
3775 ptr_arg++;
3776 }
3777 if (*ptr_arg)
3778 break;
3779 cur_arg++;
3780 }
3781 /* now ptr_arg points to the beginning of a word past any possible
3782 * exclamation mark, and cur_arg is the argument which holds this word.
3783 */
3784 if (strcmp(ptr_arg, "status") == 0) {
3785 if (!*(args[cur_arg + 1])) {
3786 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3787 file, linenum, args[0], args[1], ptr_arg);
3788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
3790 }
3791 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003792 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003793 curproxy->expect_str = strdup(args[cur_arg + 1]);
3794 }
3795 else if (strcmp(ptr_arg, "string") == 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_STR;
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, "rstatus") == 0) {
3807 if (!*(args[cur_arg + 1])) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> 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_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003814 free(curproxy->expect_str);
3815 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3816 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003817 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3818 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3819 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3820 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 }
3825 else if (strcmp(ptr_arg, "rstring") == 0) {
3826 if (!*(args[cur_arg + 1])) {
3827 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3828 file, linenum, args[0], args[1], ptr_arg);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003833 free(curproxy->expect_str);
3834 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3835 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003836 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3837 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3838 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3839 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 }
3844 else {
3845 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3846 file, linenum, args[0], args[1], ptr_arg);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003851 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003852 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 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003855 }
3856 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003857 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003858 if (curproxy == &defproxy) {
3859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003862 }
3863
Willy Tarreaub80c2302007-11-30 20:51:32 +01003864 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866
3867 if (strcmp(args[1], "fail") == 0) {
3868 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003869 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003870 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3871 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003874 }
3875
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003876 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3877 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3878 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881 }
3882 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3883 }
3884 else {
3885 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003888 }
3889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890#ifdef TPROXY
3891 else if (!strcmp(args[0], "transparent")) {
3892 /* enable transparent proxy connections */
3893 curproxy->options |= PR_O_TRANSP;
3894 }
3895#endif
3896 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003899
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 if (*(args[1]) == 0) {
3901 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 }
3905 curproxy->maxconn = atol(args[1]);
3906 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003907 else if (!strcmp(args[0], "backlog")) { /* backlog */
3908 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003910
3911 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 Tarreauc73ce2b2008-01-06 10:55:10 +01003915 }
3916 curproxy->backlog = atol(args[1]);
3917 }
Willy Tarreau86034312006-12-29 00:10:33 +01003918 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003919 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003921
Willy Tarreau86034312006-12-29 00:10:33 +01003922 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 Tarreau86034312006-12-29 00:10:33 +01003926 }
3927 curproxy->fullconn = atol(args[1]);
3928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3930 if (*(args[1]) == 0) {
3931 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003935 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3936 if (err) {
3937 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3938 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003941 }
3942 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 }
3944 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003945 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (curproxy == &defproxy) {
3947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003951 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003953
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 if (strchr(args[1], ':') == NULL) {
3955 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003959 sk = str2sa(args[1]);
3960 if (!sk) {
3961 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
3964 }
3965 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003966 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
3968 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003971
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003972 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3973 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003978 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3979 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3980 err_code |= ERR_WARN;
3981
3982 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3983 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3984 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3985 }
3986 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3987 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3988 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3989 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003990 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3991 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3992 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3993 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003994 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003995 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
3999 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004000 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 char *rport, *raddr;
4003 short realport = 0;
4004 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004006 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004011 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013
4014 if (!*args[2]) {
4015 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004020
4021 err = invalid_char(args[1]);
4022 if (err) {
4023 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4024 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004027 }
4028
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004030 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004031
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004032 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4033 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4034 err_code |= ERR_ALERT | ERR_ABORT;
4035 goto out;
4036 }
4037
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004038 /* the servers are linked backwards first */
4039 newsrv->next = curproxy->srv;
4040 curproxy->srv = newsrv;
4041 newsrv->proxy = curproxy;
4042 newsrv->conf.file = file;
4043 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044
Simon Hormanaf514952011-06-21 14:34:57 +09004045 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 LIST_INIT(&newsrv->pendconns);
4047 do_check = 0;
4048 newsrv->state = SRV_RUNNING; /* early server setup */
4049 newsrv->last_change = now.tv_sec;
4050 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004053 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004054 * - IP: => port=+0, relative
4055 * - IP:N => port=N, absolute
4056 * - IP:+N => port=+N, relative
4057 * - IP:-N => port=-N, relative
4058 */
4059 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004060 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004061 if (rport) {
4062 *rport++ = 0;
4063 realport = atol(rport);
4064 if (!isdigit((unsigned char)*rport))
4065 newsrv->state |= SRV_MAPPORTS;
4066 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068
Willy Tarreaufab5a432011-03-04 15:31:53 +01004069 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004070 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004071 if (!sk) {
4072 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004077 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004078 newsrv->sock = &sock_raw;
4079 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004080
4081 if (!sk) {
4082 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4083 file, linenum, newsrv->addr.ss_family, args[2]);
4084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
4086 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004087 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004088
4089 newsrv->check_port = curproxy->defsrv.check_port;
4090 newsrv->inter = curproxy->defsrv.inter;
4091 newsrv->fastinter = curproxy->defsrv.fastinter;
4092 newsrv->downinter = curproxy->defsrv.downinter;
4093 newsrv->rise = curproxy->defsrv.rise;
4094 newsrv->fall = curproxy->defsrv.fall;
4095 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4096 newsrv->minconn = curproxy->defsrv.minconn;
4097 newsrv->maxconn = curproxy->defsrv.maxconn;
4098 newsrv->slowstart = curproxy->defsrv.slowstart;
4099 newsrv->onerror = curproxy->defsrv.onerror;
4100 newsrv->consecutive_errors_limit
4101 = curproxy->defsrv.consecutive_errors_limit;
4102 newsrv->uweight = newsrv->iweight
4103 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004105 newsrv->curfd = -1; /* no health-check in progress */
4106 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004108 cur_arg = 3;
4109 } else {
4110 newsrv = &curproxy->defsrv;
4111 cur_arg = 1;
4112 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004113
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004115 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004116 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004117
4118 if (!*args[cur_arg + 1]) {
4119 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4120 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004123 }
4124
4125 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004126 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004127
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004128 if (newsrv->puid <= 0) {
4129 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004130 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004133 }
4134
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004135 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4136 if (node) {
4137 struct server *target = container_of(node, struct server, conf.id);
4138 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4139 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004144 cur_arg += 2;
4145 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004146 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 newsrv->cookie = strdup(args[cur_arg + 1]);
4148 newsrv->cklen = strlen(args[cur_arg + 1]);
4149 cur_arg += 2;
4150 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004151 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004152 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4153 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4154 cur_arg += 2;
4155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004157 if (!*args[cur_arg + 1]) {
4158 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4159 file, linenum, args[cur_arg]);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
4163
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004165 if (newsrv->rise <= 0) {
4166 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4167 file, linenum, args[cur_arg]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
Willy Tarreau96839092010-03-29 10:02:24 +02004172 if (newsrv->health)
4173 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 cur_arg += 2;
4175 }
4176 else if (!strcmp(args[cur_arg], "fall")) {
4177 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004178
4179 if (!*args[cur_arg + 1]) {
4180 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4181 file, linenum, args[cur_arg]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
4186 if (newsrv->fall <= 0) {
4187 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4188 file, linenum, args[cur_arg]);
4189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
4191 }
4192
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 cur_arg += 2;
4194 }
4195 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004196 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4197 if (err) {
4198 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4199 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004202 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004203 if (val <= 0) {
4204 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4205 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004208 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004209 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 cur_arg += 2;
4211 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004212 else if (!strcmp(args[cur_arg], "fastinter")) {
4213 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4214 if (err) {
4215 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4216 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004219 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004220 if (val <= 0) {
4221 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4222 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004225 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004226 newsrv->fastinter = val;
4227 cur_arg += 2;
4228 }
4229 else if (!strcmp(args[cur_arg], "downinter")) {
4230 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4231 if (err) {
4232 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4233 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004236 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004237 if (val <= 0) {
4238 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4239 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004242 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004243 newsrv->downinter = val;
4244 cur_arg += 2;
4245 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004246 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004247 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004248 if (!sk) {
4249 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004254 cur_arg += 2;
4255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004256 else if (!strcmp(args[cur_arg], "port")) {
4257 newsrv->check_port = atol(args[cur_arg + 1]);
4258 cur_arg += 2;
4259 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004260 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 newsrv->state |= SRV_BACKUP;
4262 cur_arg ++;
4263 }
Simon Hormanfa461682011-06-25 09:39:49 +09004264 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4265 newsrv->state |= SRV_NON_STICK;
4266 cur_arg ++;
4267 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004268 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4269 newsrv->state |= SRV_SEND_PROXY;
4270 cur_arg ++;
4271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004272 else if (!strcmp(args[cur_arg], "weight")) {
4273 int w;
4274 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004275 if (w < 0 || w > 256) {
4276 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004281 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 cur_arg += 2;
4283 }
4284 else if (!strcmp(args[cur_arg], "minconn")) {
4285 newsrv->minconn = atol(args[cur_arg + 1]);
4286 cur_arg += 2;
4287 }
4288 else if (!strcmp(args[cur_arg], "maxconn")) {
4289 newsrv->maxconn = atol(args[cur_arg + 1]);
4290 cur_arg += 2;
4291 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004292 else if (!strcmp(args[cur_arg], "maxqueue")) {
4293 newsrv->maxqueue = atol(args[cur_arg + 1]);
4294 cur_arg += 2;
4295 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004296 else if (!strcmp(args[cur_arg], "slowstart")) {
4297 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004298 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004299 if (err) {
4300 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4301 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004304 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004305 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004306 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4307 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004310 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004311 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004312 cur_arg += 2;
4313 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004314 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004315
4316 if (!*args[cur_arg + 1]) {
4317 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4318 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004321 }
4322
4323 newsrv->trackit = strdup(args[cur_arg + 1]);
4324
4325 cur_arg += 2;
4326 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004327 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 global.maxsock++;
4329 do_check = 1;
4330 cur_arg += 1;
4331 }
Willy Tarreau96839092010-03-29 10:02:24 +02004332 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4333 newsrv->state |= SRV_MAINTAIN;
4334 newsrv->state &= ~SRV_RUNNING;
4335 newsrv->health = 0;
4336 cur_arg += 1;
4337 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004338 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004339 if (!strcmp(args[cur_arg + 1], "none"))
4340 newsrv->observe = HANA_OBS_NONE;
4341 else if (!strcmp(args[cur_arg + 1], "layer4"))
4342 newsrv->observe = HANA_OBS_LAYER4;
4343 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4344 if (curproxy->mode != PR_MODE_HTTP) {
4345 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4346 file, linenum, args[cur_arg + 1]);
4347 err_code |= ERR_ALERT;
4348 }
4349 newsrv->observe = HANA_OBS_LAYER7;
4350 }
4351 else {
4352 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004353 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004354 file, linenum, args[cur_arg], args[cur_arg + 1]);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
4358
4359 cur_arg += 2;
4360 }
4361 else if (!strcmp(args[cur_arg], "on-error")) {
4362 if (!strcmp(args[cur_arg + 1], "fastinter"))
4363 newsrv->onerror = HANA_ONERR_FASTINTER;
4364 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4365 newsrv->onerror = HANA_ONERR_FAILCHK;
4366 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4367 newsrv->onerror = HANA_ONERR_SUDDTH;
4368 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4369 newsrv->onerror = HANA_ONERR_MARKDWN;
4370 else {
4371 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004372 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004373 file, linenum, args[cur_arg], args[cur_arg + 1]);
4374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
4376 }
4377
4378 cur_arg += 2;
4379 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004380 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4381 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4382 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4383 else {
4384 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4385 file, linenum, args[cur_arg], args[cur_arg + 1]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
4389
4390 cur_arg += 2;
4391 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004392 else if (!strcmp(args[cur_arg], "error-limit")) {
4393 if (!*args[cur_arg + 1]) {
4394 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4395 file, linenum, args[cur_arg]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4401
4402 if (newsrv->consecutive_errors_limit <= 0) {
4403 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4404 file, linenum, args[cur_arg]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004408 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004409 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004410 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004411 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004412 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004413
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004415#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004416 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004417 file, linenum, "source", "usesrc");
4418#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004419 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004420 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004421#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 }
4425 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004426 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4427 if (!sk) {
4428 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004433
4434 if (port_low != port_high) {
4435 int i;
4436 if (port_low <= 0 || port_low > 65535 ||
4437 port_high <= 0 || port_high > 65535 ||
4438 port_low > port_high) {
4439 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4440 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004443 }
4444 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4445 for (i = 0; i < newsrv->sport_range->size; i++)
4446 newsrv->sport_range->ports[i] = port_low + i;
4447 }
4448
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004450 while (*(args[cur_arg])) {
4451 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004452#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4453#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004454 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4455 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4456 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004459 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004460#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004461 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004462 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004463 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004466 }
4467 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004468 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004469 newsrv->state |= SRV_TPROXY_CLI;
4470 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004471 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004472 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004473 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4474 char *name, *end;
4475
4476 name = args[cur_arg+1] + 7;
4477 while (isspace(*name))
4478 name++;
4479
4480 end = name;
4481 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4482 end++;
4483
4484 newsrv->state &= ~SRV_TPROXY_MASK;
4485 newsrv->state |= SRV_TPROXY_DYN;
4486 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4487 newsrv->bind_hdr_len = end - name;
4488 memcpy(newsrv->bind_hdr_name, name, end - name);
4489 newsrv->bind_hdr_name[end-name] = '\0';
4490 newsrv->bind_hdr_occ = -1;
4491
4492 /* now look for an occurrence number */
4493 while (isspace(*end))
4494 end++;
4495 if (*end == ',') {
4496 end++;
4497 name = end;
4498 if (*end == '-')
4499 end++;
4500 while (isdigit(*end))
4501 end++;
4502 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4503 }
4504
4505 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4506 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4507 " occurrences values smaller than %d.\n",
4508 file, linenum, MAX_HDR_HISTORY);
4509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
4511 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004512 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004513 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004514 if (!sk) {
4515 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
4518 }
4519 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004521 }
4522 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004523#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004524 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004525#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004526 cur_arg += 2;
4527 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004528#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004530 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004533#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4534 } /* "usesrc" */
4535
4536 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4537#ifdef SO_BINDTODEVICE
4538 if (!*args[cur_arg + 1]) {
4539 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4540 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004543 }
4544 if (newsrv->iface_name)
4545 free(newsrv->iface_name);
4546
4547 newsrv->iface_name = strdup(args[cur_arg + 1]);
4548 newsrv->iface_len = strlen(newsrv->iface_name);
4549 global.last_checks |= LSTCHK_NETADM;
4550#else
4551 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4552 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004555#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 cur_arg += 2;
4557 continue;
4558 }
4559 /* this keyword in not an option of "source" */
4560 break;
4561 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004563 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004564 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4565 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004570 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004571 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 +01004572 file, linenum, newsrv->id);
4573 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004574 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 +01004575 file, linenum);
4576
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 }
4581
4582 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004583 if (newsrv->trackit) {
4584 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004588 }
4589
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004590 /* try to get the port from check_addr if check_port not set */
4591 if (!newsrv->check_port)
4592 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004593
Willy Tarreaubaaee002006-06-26 02:48:02 +02004594 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4595 newsrv->check_port = realport; /* by default */
4596 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004597 /* not yet valid, because no port was set on
4598 * the server either. We'll check if we have
4599 * a known port on the first listener.
4600 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004601 struct listener *l = curproxy->listen;
4602 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4603 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004604 }
4605 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4607 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004611
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004612 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004613 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004614 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4615 err_code |= ERR_ALERT | ERR_ABORT;
4616 goto out;
4617 }
4618
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004619 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 newsrv->state |= SRV_CHECKED;
4621 }
4622
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004623 if (!defsrv) {
4624 if (newsrv->state & SRV_BACKUP)
4625 curproxy->srv_bck++;
4626 else
4627 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004628
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 newsrv->prev_state = newsrv->state;
4630 }
William Lallemanda73203e2012-03-12 12:48:57 +01004631 }
4632
4633 else if (strcmp(args[0], "unique-id-format") == 0) {
4634 if (!*(args[1])) {
4635 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
4638 }
4639 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004640 }
William Lallemanda73203e2012-03-12 12:48:57 +01004641
4642 else if (strcmp(args[0], "unique-id-header") == 0) {
4643 if (!*(args[1])) {
4644 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
4648 free(curproxy->header_unique_id);
4649 curproxy->header_unique_id = strdup(args[1]);
4650 }
4651
William Lallemand723b73a2012-02-08 16:37:49 +01004652 else if (strcmp(args[0], "log-format") == 0) {
4653 if (!*(args[1])) {
4654 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
4657 }
William Lallemand1d705562012-03-12 12:46:41 +01004658 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
William Lallemand723b73a2012-02-08 16:37:49 +01004660
William Lallemand0f99e342011-10-12 17:50:54 +02004661 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4662 /* delete previous herited or defined syslog servers */
4663 struct logsrv *back;
4664
4665 if (*(args[1]) != 0) {
4666 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670
William Lallemand723b73a2012-02-08 16:37:49 +01004671 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4672 LIST_DEL(&tmplogsrv->list);
4673 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004674 }
4675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004677 struct logsrv *logsrv;
4678
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004680 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004681 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004682 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004683 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004684 LIST_INIT(&node->list);
4685 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004689
4690 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691
William Lallemand0f99e342011-10-12 17:50:54 +02004692 logsrv->facility = get_log_facility(args[2]);
4693 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 }
4699
William Lallemand0f99e342011-10-12 17:50:54 +02004700 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->level = get_log_level(args[3]);
4703 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 }
4710
William Lallemand0f99e342011-10-12 17:50:54 +02004711 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004712 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->minlvl = get_log_level(args[4]);
4714 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004715 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004719 }
4720 }
4721
Robert Tsai81ae1952007-12-05 10:47:29 +01004722 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004723 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004724 if (!sk) {
4725 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004726 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
William Lallemand0f99e342011-10-12 17:50:54 +02004730 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004731 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004732 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004733 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004734 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
William Lallemand0f99e342011-10-12 17:50:54 +02004738 logsrv->addr = *sk;
4739 if (!get_host_port(&logsrv->addr))
4740 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
William Lallemand0f99e342011-10-12 17:50:54 +02004742
4743 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
4745 else {
4746 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 }
4752 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004753 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004754 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004755
Willy Tarreau977b8e42006-12-29 14:19:17 +01004756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004758
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4761 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004765
4766 /* we must first clear any optional default setting */
4767 curproxy->options &= ~PR_O_TPXY_MASK;
4768 free(curproxy->iface_name);
4769 curproxy->iface_name = NULL;
4770 curproxy->iface_len = 0;
4771
Willy Tarreaud5191e72010-02-09 20:50:45 +01004772 sk = str2sa(args[1]);
4773 if (!sk) {
4774 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
4778 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004780
4781 cur_arg = 2;
4782 while (*(args[cur_arg])) {
4783 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004784#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4785#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004786 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4787 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4788 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004791 }
4792#endif
4793 if (!*args[cur_arg + 1]) {
4794 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4795 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798 }
4799
4800 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004801 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004802 curproxy->options |= PR_O_TPXY_CLI;
4803 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004804 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004805 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004806 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4807 char *name, *end;
4808
4809 name = args[cur_arg+1] + 7;
4810 while (isspace(*name))
4811 name++;
4812
4813 end = name;
4814 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4815 end++;
4816
4817 curproxy->options &= ~PR_O_TPXY_MASK;
4818 curproxy->options |= PR_O_TPXY_DYN;
4819 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4820 curproxy->bind_hdr_len = end - name;
4821 memcpy(curproxy->bind_hdr_name, name, end - name);
4822 curproxy->bind_hdr_name[end-name] = '\0';
4823 curproxy->bind_hdr_occ = -1;
4824
4825 /* now look for an occurrence number */
4826 while (isspace(*end))
4827 end++;
4828 if (*end == ',') {
4829 end++;
4830 name = end;
4831 if (*end == '-')
4832 end++;
4833 while (isdigit(*end))
4834 end++;
4835 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4836 }
4837
4838 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4839 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4840 " occurrences values smaller than %d.\n",
4841 file, linenum, MAX_HDR_HISTORY);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004845 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004846 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004847 if (!sk) {
4848 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004854 }
4855 global.last_checks |= LSTCHK_NETADM;
4856#if !defined(CONFIG_HAP_LINUX_TPROXY)
4857 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004858#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004859#else /* no TPROXY support */
4860 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004861 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004864#endif
4865 cur_arg += 2;
4866 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004867 }
4868
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004869 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4870#ifdef SO_BINDTODEVICE
4871 if (!*args[cur_arg + 1]) {
4872 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4873 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004876 }
4877 if (curproxy->iface_name)
4878 free(curproxy->iface_name);
4879
4880 curproxy->iface_name = strdup(args[cur_arg + 1]);
4881 curproxy->iface_len = strlen(curproxy->iface_name);
4882 global.last_checks |= LSTCHK_NETADM;
4883#else
4884 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4885 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004888#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 cur_arg += 2;
4890 continue;
4891 }
4892 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4893 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004898 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4899 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4900 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911
4912 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004913 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004914 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004920 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004921 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
4925 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004927 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004928 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004941 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004946 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004952 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004953 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004959 }
4960 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974
4975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005004 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005005 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005009 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005017 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005018
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 if (curproxy == &defproxy) {
5020 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005024 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 if (*(args[1]) == 0) {
5028 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005032
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005033 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005034 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5035 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5036 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039 }
5040 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5041 }
5042 else if (*args[2]) {
5043 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5044 file, linenum, args[0], args[2]);
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
5048
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005049 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005050 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005051 wl->s = strdup(args[1]);
5052 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005053 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
5055 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005062
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005064 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005065 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
5069 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005071 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005072 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
5076 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005078 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005079 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5086 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005092 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005093 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
5097 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005099 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005100 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
5111 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005112 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005113
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 if (curproxy == &defproxy) {
5115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005119 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 if (*(args[1]) == 0) {
5123 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005128 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005129 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5130 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5131 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135 err_code |= warnif_cond_requires_req(cond, file, linenum);
5136 }
5137 else if (*args[2]) {
5138 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5139 file, linenum, args[0], args[2]);
5140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
5143
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005144 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005145 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005146 wl->s = strdup(args[1]);
5147 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 else if (!strcmp(args[0], "errorloc") ||
5150 !strcmp(args[0], "errorloc302") ||
5151 !strcmp(args[0], "errorloc303")) { /* error location */
5152 int errnum, errlen;
5153 char *err;
5154
Willy Tarreau977b8e42006-12-29 14:19:17 +01005155 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005159 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 }
5163
5164 errnum = atol(args[1]);
5165 if (!strcmp(args[0], "errorloc303")) {
5166 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5167 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5168 } else {
5169 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5170 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5171 }
5172
Willy Tarreau0f772532006-12-23 20:51:41 +01005173 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5174 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005175 chunk_destroy(&curproxy->errmsg[rc]);
5176 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005177 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005180
5181 if (rc >= HTTP_ERR_SIZE) {
5182 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5183 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 free(err);
5185 }
5186 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5188 int errnum, errlen, fd;
5189 char *err;
5190 struct stat stat;
5191
5192 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005194
5195 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005196 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005199 }
5200
5201 fd = open(args[2], O_RDONLY);
5202 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5203 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5204 file, linenum, args[2], args[1]);
5205 if (fd >= 0)
5206 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 }
5210
Willy Tarreau27a674e2009-08-17 07:23:33 +02005211 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 errlen = stat.st_size;
5213 } else {
5214 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005215 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005217 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005218 }
5219
5220 err = malloc(errlen); /* malloc() must succeed during parsing */
5221 errnum = read(fd, err, errlen);
5222 if (errnum != errlen) {
5223 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5224 file, linenum, args[2], args[1]);
5225 close(fd);
5226 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 }
5230 close(fd);
5231
5232 errnum = atol(args[1]);
5233 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5234 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005235 chunk_destroy(&curproxy->errmsg[rc]);
5236 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005237 break;
5238 }
5239 }
5240
5241 if (rc >= HTTP_ERR_SIZE) {
5242 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5243 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005245 free(err);
5246 }
5247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005249 struct cfg_kw_list *kwl;
5250 int index;
5251
5252 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5253 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5254 if (kwl->kw[index].section != CFG_LISTEN)
5255 continue;
5256 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5257 /* prepare error message just in case */
5258 snprintf(trash, sizeof(trash),
5259 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005260 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005261 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005262 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005265 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005266 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005267 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_WARN;
5269 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005270 }
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005272 }
5273 }
5274 }
5275
Willy Tarreau6daf3432008-01-22 16:44:08 +01005276 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
Willy Tarreau93893792009-07-23 13:19:11 +02005280 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005281 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005282 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283}
5284
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005285int
5286cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5287{
5288
5289 int err_code = 0;
5290 const char *err;
5291
5292 if (!strcmp(args[0], "userlist")) { /* new userlist */
5293 struct userlist *newul;
5294
5295 if (!*args[1]) {
5296 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5297 file, linenum, args[0]);
5298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
5300 }
5301
5302 err = invalid_char(args[1]);
5303 if (err) {
5304 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5305 file, linenum, *err, args[0], args[1]);
5306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
5308 }
5309
5310 for (newul = userlist; newul; newul = newul->next)
5311 if (!strcmp(newul->name, args[1])) {
5312 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5313 file, linenum, args[1]);
5314 err_code |= ERR_WARN;
5315 goto out;
5316 }
5317
5318 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5319 if (!newul) {
5320 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5321 err_code |= ERR_ALERT | ERR_ABORT;
5322 goto out;
5323 }
5324
5325 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5326 newul->name = strdup(args[1]);
5327
5328 if (!newul->groupusers | !newul->name) {
5329 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5330 err_code |= ERR_ALERT | ERR_ABORT;
5331 goto out;
5332 }
5333
5334 newul->next = userlist;
5335 userlist = newul;
5336
5337 } else if (!strcmp(args[0], "group")) { /* new group */
5338 int cur_arg, i;
5339 const char *err;
5340
5341 if (!*args[1]) {
5342 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5343 file, linenum, args[0]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347
5348 err = invalid_char(args[1]);
5349 if (err) {
5350 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5351 file, linenum, *err, args[0], args[1]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355
5356 for(i = 0; i < userlist->grpcnt; i++)
5357 if (!strcmp(userlist->groups[i], args[1])) {
5358 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5359 file, linenum, args[1], userlist->name);
5360 err_code |= ERR_ALERT;
5361 goto out;
5362 }
5363
5364 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5365 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5366 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370
5371 cur_arg = 2;
5372
5373 while (*args[cur_arg]) {
5374 if (!strcmp(args[cur_arg], "users")) {
5375 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5376 cur_arg += 2;
5377 continue;
5378 } else {
5379 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5380 file, linenum, args[0]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 }
5385
5386 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5387 } else if (!strcmp(args[0], "user")) { /* new user */
5388 struct auth_users *newuser;
5389 int cur_arg;
5390
5391 if (!*args[1]) {
5392 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5393 file, linenum, args[0]);
5394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
5396 }
5397
5398 for (newuser = userlist->users; newuser; newuser = newuser->next)
5399 if (!strcmp(newuser->user, args[1])) {
5400 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5401 file, linenum, args[1], userlist->name);
5402 err_code |= ERR_ALERT;
5403 goto out;
5404 }
5405
5406 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5407 if (!newuser) {
5408 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5409 err_code |= ERR_ALERT | ERR_ABORT;
5410 goto out;
5411 }
5412
5413 newuser->user = strdup(args[1]);
5414
5415 newuser->next = userlist->users;
5416 userlist->users = newuser;
5417
5418 cur_arg = 2;
5419
5420 while (*args[cur_arg]) {
5421 if (!strcmp(args[cur_arg], "password")) {
5422#ifndef CONFIG_HAP_CRYPT
5423 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5424 file, linenum);
5425 err_code |= ERR_ALERT;
5426#endif
5427 newuser->pass = strdup(args[cur_arg + 1]);
5428 cur_arg += 2;
5429 continue;
5430 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5431 newuser->pass = strdup(args[cur_arg + 1]);
5432 newuser->flags |= AU_O_INSECURE;
5433 cur_arg += 2;
5434 continue;
5435 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005436 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005437 cur_arg += 2;
5438 continue;
5439 } else {
5440 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5441 file, linenum, args[0]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445 }
5446 } else {
5447 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 }
5450
5451out:
5452 return err_code;
5453}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454
5455/*
5456 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005457 * Returns the error code, 0 if OK, or any combination of :
5458 * - ERR_ABORT: must abort ASAP
5459 * - ERR_FATAL: we can continue parsing but not start the service
5460 * - ERR_WARN: a warning has been emitted
5461 * - ERR_ALERT: an alert has been emitted
5462 * Only the two first ones can stop processing, the two others are just
5463 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005465int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005467 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 FILE *f;
5469 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005471 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 if ((f=fopen(file,"r")) == NULL)
5474 return -1;
5475
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005476 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005477 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005478 char *end;
5479 char *args[MAX_LINE_ARGS + 1];
5480 char *line = thisline;
5481
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 linenum++;
5483
5484 end = line + strlen(line);
5485
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005486 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5487 /* Check if we reached the limit and the last char is not \n.
5488 * Watch out for the last line without the terminating '\n'!
5489 */
5490 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005491 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005493 }
5494
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005496 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 line++;
5498
5499 arg = 0;
5500 args[arg] = line;
5501
5502 while (*line && arg < MAX_LINE_ARGS) {
5503 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5504 * C equivalent value. Other combinations left unchanged (eg: \1).
5505 */
5506 if (*line == '\\') {
5507 int skip = 0;
5508 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5509 *line = line[1];
5510 skip = 1;
5511 }
5512 else if (line[1] == 'r') {
5513 *line = '\r';
5514 skip = 1;
5515 }
5516 else if (line[1] == 'n') {
5517 *line = '\n';
5518 skip = 1;
5519 }
5520 else if (line[1] == 't') {
5521 *line = '\t';
5522 skip = 1;
5523 }
5524 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005525 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 unsigned char hex1, hex2;
5527 hex1 = toupper(line[2]) - '0';
5528 hex2 = toupper(line[3]) - '0';
5529 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5530 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5531 *line = (hex1<<4) + hex2;
5532 skip = 3;
5533 }
5534 else {
5535 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005536 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
5538 }
5539 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005540 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 end -= skip;
5542 }
5543 line++;
5544 }
5545 else if (*line == '#' || *line == '\n' || *line == '\r') {
5546 /* end of string, end of loop */
5547 *line = 0;
5548 break;
5549 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005550 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005552 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005553 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 line++;
5555 args[++arg] = line;
5556 }
5557 else {
5558 line++;
5559 }
5560 }
5561
5562 /* empty line */
5563 if (!**args)
5564 continue;
5565
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005566 if (*line) {
5567 /* we had to stop due to too many args.
5568 * Let's terminate the string, print the offending part then cut the
5569 * last arg.
5570 */
5571 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5572 line++;
5573 *line = '\0';
5574
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005575 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005576 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005577 err_code |= ERR_ALERT | ERR_FATAL;
5578 args[arg] = line;
5579 }
5580
Willy Tarreau540abe42007-05-02 20:50:16 +02005581 /* zero out remaining args and ensure that at least one entry
5582 * is zeroed out.
5583 */
5584 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 args[arg] = line;
5586 }
5587
Willy Tarreau3842f002009-06-14 11:39:52 +02005588 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005589 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005590 char *tmp;
5591
Willy Tarreau3842f002009-06-14 11:39:52 +02005592 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005593 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005594 for (arg=0; *args[arg+1]; arg++)
5595 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005596 *tmp = '\0'; // fix the next arg to \0
5597 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005598 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005599 else if (!strcmp(args[0], "default")) {
5600 kwm = KWM_DEF;
5601 for (arg=0; *args[arg+1]; arg++)
5602 args[arg] = args[arg+1]; // shift args after inversion
5603 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005604
William Lallemand0f99e342011-10-12 17:50:54 +02005605 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5606 strcmp(args[0], "log") != 0) {
5607 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005608 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005609 }
5610
Willy Tarreau977b8e42006-12-29 14:19:17 +01005611 if (!strcmp(args[0], "listen") ||
5612 !strcmp(args[0], "frontend") ||
5613 !strcmp(args[0], "backend") ||
5614 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005615 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005617 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005618 cursection = strdup(args[0]);
5619 }
5620 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005622 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005623 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005624 }
5625 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005626 confsect = CFG_USERLIST;
5627 free(cursection);
5628 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005629 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005630 else if (!strcmp(args[0], "peers")) {
5631 confsect = CFG_PEERS;
5632 free(cursection);
5633 cursection = strdup(args[0]);
5634 }
5635
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 /* else it's a section keyword */
5637
5638 switch (confsect) {
5639 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 break;
5642 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005643 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005645 case CFG_USERLIST:
5646 err_code |= cfg_parse_users(file, linenum, args, kwm);
5647 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005648 case CFG_PEERS:
5649 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5650 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005652 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005653 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005654 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005655
5656 if (err_code & ERR_ABORT)
5657 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005659 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005660 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005662 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005663}
5664
Willy Tarreaubb925012009-07-23 13:36:36 +02005665/*
5666 * Returns the error code, 0 if OK, or any combination of :
5667 * - ERR_ABORT: must abort ASAP
5668 * - ERR_FATAL: we can continue parsing but not start the service
5669 * - ERR_WARN: a warning has been emitted
5670 * - ERR_ALERT: an alert has been emitted
5671 * Only the two first ones can stop processing, the two others are just
5672 * indicators.
5673 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005674int check_config_validity()
5675{
5676 int cfgerr = 0;
5677 struct proxy *curproxy = NULL;
5678 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005679 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005680 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005681 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682
5683 /*
5684 * Now, check for the integrity of all that we have collected.
5685 */
5686
5687 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005688 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005690 /* first, we will invert the proxy list order */
5691 curproxy = NULL;
5692 while (proxy) {
5693 struct proxy *next;
5694
5695 next = proxy->next;
5696 proxy->next = curproxy;
5697 curproxy = proxy;
5698 if (!next)
5699 break;
5700 proxy = next;
5701 }
5702
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005704 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005705 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005706 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005707 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005708 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005709 unsigned int next_id;
5710
5711 if (!curproxy->uuid) {
5712 /* proxy ID not set, use automatic numbering with first
5713 * spare entry starting with next_pxid.
5714 */
5715 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5716 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5717 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005718 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005719 next_pxid++;
5720
Willy Tarreau55ea7572007-06-17 19:56:27 +02005721
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005723 /* ensure we don't keep listeners uselessly bound */
5724 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 curproxy = curproxy->next;
5726 continue;
5727 }
5728
Willy Tarreauff01a212009-03-15 13:46:16 +01005729 switch (curproxy->mode) {
5730 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005731 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005732 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005733 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5734 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005735 cfgerr++;
5736 }
5737
5738 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005739 Warning("config : servers will be ignored for %s '%s'.\n",
5740 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005741 break;
5742
5743 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005744 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005745 break;
5746
5747 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005748 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005749 break;
5750 }
5751
5752 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005753 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5754 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 cfgerr++;
5756 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005757
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005758 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005759 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005760 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005761 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5762 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005763 cfgerr++;
5764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005766 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005767 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5768 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005769 cfgerr++;
5770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005772 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005773 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5774 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005775 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005776 }
5777 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005778 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005779 /* If no LB algo is set in a backend, and we're not in
5780 * transparent mode, dispatch mode nor proxy mode, we
5781 * want to use balance roundrobin by default.
5782 */
5783 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5784 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005787
Willy Tarreau1620ec32011-08-06 17:05:02 +02005788 if (curproxy->options & PR_O_DISPATCH)
5789 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5790 else if (curproxy->options & PR_O_HTTP_PROXY)
5791 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5792 else if (curproxy->options & PR_O_TRANSP)
5793 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005794
Willy Tarreau1620ec32011-08-06 17:05:02 +02005795 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5796 if (curproxy->options & PR_O_DISABLE404) {
5797 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5798 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5799 err_code |= ERR_WARN;
5800 curproxy->options &= ~PR_O_DISABLE404;
5801 }
5802 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5803 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5804 "send-state", proxy_type_str(curproxy), curproxy->id);
5805 err_code |= ERR_WARN;
5806 curproxy->options &= ~PR_O2_CHK_SNDST;
5807 }
Willy Tarreauef781042010-01-27 11:53:01 +01005808 }
5809
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005810 /* if a default backend was specified, let's find it */
5811 if (curproxy->defbe.name) {
5812 struct proxy *target;
5813
Alex Williams96532db2009-11-01 21:27:13 -05005814 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005815 if (!target) {
5816 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5817 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005818 cfgerr++;
5819 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005820 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5821 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005822 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005823 } else {
5824 free(curproxy->defbe.name);
5825 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005826 /* we force the backend to be present on at least all of
5827 * the frontend's processes.
5828 */
5829 target->bind_proc = curproxy->bind_proc ?
5830 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005831
5832 /* Emit a warning if this proxy also has some servers */
5833 if (curproxy->srv) {
5834 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5835 curproxy->id);
5836 err_code |= ERR_WARN;
5837 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 }
5839 }
5840
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005841 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005842 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5843 /* map jump target for ACT_SETBE in req_rep chain */
5844 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005845 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005846 struct proxy *target;
5847
Willy Tarreaua496b602006-12-17 23:15:24 +01005848 if (exp->action != ACT_SETBE)
5849 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005850
Alex Williams96532db2009-11-01 21:27:13 -05005851 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005852 if (!target) {
5853 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5854 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005855 cfgerr++;
5856 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005857 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5858 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005859 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005860 } else {
5861 free((void *)exp->replace);
5862 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005863 /* we force the backend to be present on at least all of
5864 * the frontend's processes.
5865 */
5866 target->bind_proc = curproxy->bind_proc ?
5867 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005868 }
5869 }
5870 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005871
5872 /* find the target proxy for 'use_backend' rules */
5873 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005874 struct proxy *target;
5875
Alex Williams96532db2009-11-01 21:27:13 -05005876 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005877
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005878 if (!target) {
5879 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5880 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005881 cfgerr++;
5882 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005883 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5884 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005885 cfgerr++;
5886 } else {
5887 free((void *)rule->be.name);
5888 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005889 /* we force the backend to be present on at least all of
5890 * the frontend's processes.
5891 */
5892 target->bind_proc = curproxy->bind_proc ?
5893 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005894 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005895 }
5896
5897 /* find the target proxy for 'use_backend' rules */
5898 list_for_each_entry(srule, &curproxy->server_rules, list) {
5899 struct server *target = findserver(curproxy, srule->srv.name);
5900
5901 if (!target) {
5902 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5903 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5904 cfgerr++;
5905 continue;
5906 }
5907 free((void *)srule->srv.name);
5908 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005909 }
5910
Emeric Brunb982a3d2010-01-04 15:45:53 +01005911 /* find the target table for 'stick' rules */
5912 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5913 struct proxy *target;
5914
Emeric Brun1d33b292010-01-04 15:47:17 +01005915 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5916 if (mrule->flags & STK_IS_STORE)
5917 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5918
Emeric Brunb982a3d2010-01-04 15:45:53 +01005919 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005920 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005921 else
5922 target = curproxy;
5923
5924 if (!target) {
5925 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5926 curproxy->id, mrule->table.name);
5927 cfgerr++;
5928 }
5929 else if (target->table.size == 0) {
5930 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5931 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5932 cfgerr++;
5933 }
Willy Tarreau12785782012-04-27 21:37:17 +02005934 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5935 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005936 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5937 cfgerr++;
5938 }
5939 else {
5940 free((void *)mrule->table.name);
5941 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005942 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005943 }
5944 }
5945
5946 /* find the target table for 'store response' rules */
5947 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5948 struct proxy *target;
5949
Emeric Brun1d33b292010-01-04 15:47:17 +01005950 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5951
Emeric Brunb982a3d2010-01-04 15:45:53 +01005952 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005953 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005954 else
5955 target = curproxy;
5956
5957 if (!target) {
5958 Alert("Proxy '%s': unable to find store table '%s'.\n",
5959 curproxy->id, mrule->table.name);
5960 cfgerr++;
5961 }
5962 else if (target->table.size == 0) {
5963 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5964 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5965 cfgerr++;
5966 }
Willy Tarreau12785782012-04-27 21:37:17 +02005967 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5968 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005969 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5970 cfgerr++;
5971 }
5972 else {
5973 free((void *)mrule->table.name);
5974 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005975 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005976 }
5977 }
5978
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005979 /* find the target table for 'tcp-request' layer 4 rules */
5980 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5981 struct proxy *target;
5982
Willy Tarreau56123282010-08-06 19:06:56 +02005983 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005984 continue;
5985
5986 if (trule->act_prm.trk_ctr.table.n)
5987 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5988 else
5989 target = curproxy;
5990
5991 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005992 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5993 curproxy->id, trule->act_prm.trk_ctr.table.n,
5994 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005995 cfgerr++;
5996 }
5997 else if (target->table.size == 0) {
5998 Alert("Proxy '%s': table '%s' used but not configured.\n",
5999 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6000 cfgerr++;
6001 }
6002 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006003 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 +02006004 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6005 cfgerr++;
6006 }
6007 else {
6008 free(trule->act_prm.trk_ctr.table.n);
6009 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006010 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006011 * to pass a list of counters to track and allocate them right here using
6012 * stktable_alloc_data_type().
6013 */
6014 }
6015 }
6016
Willy Tarreaud1f96522010-08-03 19:34:32 +02006017 /* find the target table for 'tcp-request' layer 6 rules */
6018 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6019 struct proxy *target;
6020
Willy Tarreau56123282010-08-06 19:06:56 +02006021 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006022 continue;
6023
6024 if (trule->act_prm.trk_ctr.table.n)
6025 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6026 else
6027 target = curproxy;
6028
6029 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006030 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6031 curproxy->id, trule->act_prm.trk_ctr.table.n,
6032 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006033 cfgerr++;
6034 }
6035 else if (target->table.size == 0) {
6036 Alert("Proxy '%s': table '%s' used but not configured.\n",
6037 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6038 cfgerr++;
6039 }
6040 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006041 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 +02006042 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6043 cfgerr++;
6044 }
6045 else {
6046 free(trule->act_prm.trk_ctr.table.n);
6047 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006048 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006049 * to pass a list of counters to track and allocate them right here using
6050 * stktable_alloc_data_type().
6051 */
6052 }
6053 }
6054
Emeric Brun32da3c42010-09-23 18:39:19 +02006055 if (curproxy->table.peers.name) {
6056 struct peers *curpeers = peers;
6057
6058 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6059 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6060 free((void *)curproxy->table.peers.name);
6061 curproxy->table.peers.p = peers;
6062 break;
6063 }
6064 }
6065
6066 if (!curpeers) {
6067 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6068 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006069 free((void *)curproxy->table.peers.name);
6070 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006071 cfgerr++;
6072 }
6073 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006074 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6075 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006076 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006077 cfgerr++;
6078 }
6079 }
6080
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006081 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006082 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006083 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6084 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6085 "proxy", curproxy->id);
6086 cfgerr++;
6087 goto out_uri_auth_compat;
6088 }
6089
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006090 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006091 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006092 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006093 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006094
Willy Tarreau95fa4692010-02-01 13:05:50 +01006095 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6096 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006097
6098 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006099 uri_auth_compat_req[i++] = "realm";
6100 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6101 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006102
Willy Tarreau95fa4692010-02-01 13:05:50 +01006103 uri_auth_compat_req[i++] = "unless";
6104 uri_auth_compat_req[i++] = "{";
6105 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6106 uri_auth_compat_req[i++] = "}";
6107 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006108
Willy Tarreauff011f22011-01-06 17:51:27 +01006109 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6110 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006111 cfgerr++;
6112 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006113 }
6114
Willy Tarreauff011f22011-01-06 17:51:27 +01006115 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006116
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006117 if (curproxy->uri_auth->auth_realm) {
6118 free(curproxy->uri_auth->auth_realm);
6119 curproxy->uri_auth->auth_realm = NULL;
6120 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006121
6122 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006123 }
6124out_uri_auth_compat:
6125
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006126 cfgerr += acl_find_targets(curproxy);
6127
Willy Tarreau2738a142006-07-08 17:28:09 +02006128 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006129 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006130 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006131 (!curproxy->timeout.connect ||
6132 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006133 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006134 " | While not properly invalid, you will certainly encounter various problems\n"
6135 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006136 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006137 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006138 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006139 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006140
Willy Tarreau1fa31262007-12-03 00:36:16 +01006141 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6142 * We must still support older configurations, so let's find out whether those
6143 * parameters have been set or must be copied from contimeouts.
6144 */
6145 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006146 if (!curproxy->timeout.tarpit ||
6147 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006148 /* tarpit timeout not set. We search in the following order:
6149 * default.tarpit, curr.connect, default.connect.
6150 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006151 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006152 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006153 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006154 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006155 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006156 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006157 }
6158 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006159 (!curproxy->timeout.queue ||
6160 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006161 /* queue timeout not set. We search in the following order:
6162 * default.queue, curr.connect, default.connect.
6163 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006164 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006165 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006166 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006167 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006168 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006169 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006170 }
6171 }
6172
Willy Tarreau1620ec32011-08-06 17:05:02 +02006173 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006174 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6175 curproxy->check_req = (char *)malloc(curproxy->check_len);
6176 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006177 }
6178
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006179 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006180 if (curproxy->nb_req_cap) {
6181 if (curproxy->mode == PR_MODE_HTTP) {
6182 curproxy->req_cap_pool = create_pool("ptrcap",
6183 curproxy->nb_req_cap * sizeof(char *),
6184 MEM_F_SHARED);
6185 } else {
6186 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6187 proxy_type_str(curproxy), curproxy->id);
6188 err_code |= ERR_WARN;
6189 curproxy->to_log &= ~LW_REQHDR;
6190 curproxy->nb_req_cap = 0;
6191 }
6192 }
6193
6194 if (curproxy->nb_rsp_cap) {
6195 if (curproxy->mode == PR_MODE_HTTP) {
6196 curproxy->rsp_cap_pool = create_pool("ptrcap",
6197 curproxy->nb_rsp_cap * sizeof(char *),
6198 MEM_F_SHARED);
6199 } else {
6200 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6201 proxy_type_str(curproxy), curproxy->id);
6202 err_code |= ERR_WARN;
6203 curproxy->to_log &= ~LW_REQHDR;
6204 curproxy->nb_rsp_cap = 0;
6205 }
6206 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006207
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 /* first, we will invert the servers list order */
6209 newsrv = NULL;
6210 while (curproxy->srv) {
6211 struct server *next;
6212
6213 next = curproxy->srv->next;
6214 curproxy->srv->next = newsrv;
6215 newsrv = curproxy->srv;
6216 if (!next)
6217 break;
6218 curproxy->srv = next;
6219 }
6220
Willy Tarreaudd701652010-05-25 23:03:02 +02006221 /* assign automatic UIDs to servers which don't have one yet */
6222 next_id = 1;
6223 newsrv = curproxy->srv;
6224 while (newsrv != NULL) {
6225 if (!newsrv->puid) {
6226 /* server ID not set, use automatic numbering with first
6227 * spare entry starting with next_svid.
6228 */
6229 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6230 newsrv->conf.id.key = newsrv->puid = next_id;
6231 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6232 }
6233 next_id++;
6234 newsrv = newsrv->next;
6235 }
6236
Willy Tarreau20697042007-11-15 23:26:18 +01006237 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006238 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239
Willy Tarreau62c3be22012-01-20 13:12:32 +01006240 /*
6241 * If this server supports a maxconn parameter, it needs a dedicated
6242 * tasks to fill the emptied slots when a connection leaves.
6243 * Also, resolve deferred tracking dependency if needed.
6244 */
6245 newsrv = curproxy->srv;
6246 while (newsrv != NULL) {
6247 if (newsrv->minconn > newsrv->maxconn) {
6248 /* Only 'minconn' was specified, or it was higher than or equal
6249 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6250 * this will avoid further useless expensive computations.
6251 */
6252 newsrv->maxconn = newsrv->minconn;
6253 } else if (newsrv->maxconn && !newsrv->minconn) {
6254 /* minconn was not specified, so we set it to maxconn */
6255 newsrv->minconn = newsrv->maxconn;
6256 }
6257
6258 if (newsrv->trackit) {
6259 struct proxy *px;
6260 struct server *srv;
6261 char *pname, *sname;
6262
6263 pname = newsrv->trackit;
6264 sname = strrchr(pname, '/');
6265
6266 if (sname)
6267 *sname++ = '\0';
6268 else {
6269 sname = pname;
6270 pname = NULL;
6271 }
6272
6273 if (pname) {
6274 px = findproxy(pname, PR_CAP_BE);
6275 if (!px) {
6276 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6277 proxy_type_str(curproxy), curproxy->id,
6278 newsrv->id, pname);
6279 cfgerr++;
6280 goto next_srv;
6281 }
6282 } else
6283 px = curproxy;
6284
6285 srv = findserver(px, sname);
6286 if (!srv) {
6287 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6288 proxy_type_str(curproxy), curproxy->id,
6289 newsrv->id, sname);
6290 cfgerr++;
6291 goto next_srv;
6292 }
6293
6294 if (!(srv->state & SRV_CHECKED)) {
6295 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6296 "tracking as it does not have checks enabled.\n",
6297 proxy_type_str(curproxy), curproxy->id,
6298 newsrv->id, px->id, srv->id);
6299 cfgerr++;
6300 goto next_srv;
6301 }
6302
6303 if (curproxy != px &&
6304 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6305 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6306 "tracking: disable-on-404 option inconsistency.\n",
6307 proxy_type_str(curproxy), curproxy->id,
6308 newsrv->id, px->id, srv->id);
6309 cfgerr++;
6310 goto next_srv;
6311 }
6312
6313 /* if the other server is forced disabled, we have to do the same here */
6314 if (srv->state & SRV_MAINTAIN) {
6315 newsrv->state |= SRV_MAINTAIN;
6316 newsrv->state &= ~SRV_RUNNING;
6317 newsrv->health = 0;
6318 }
6319
6320 newsrv->track = srv;
6321 newsrv->tracknext = srv->tracknext;
6322 srv->tracknext = newsrv;
6323
6324 free(newsrv->trackit);
6325 newsrv->trackit = NULL;
6326 }
6327 next_srv:
6328 newsrv = newsrv->next;
6329 }
6330
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006331 /* We have to initialize the server lookup mechanism depending
6332 * on what LB algorithm was choosen.
6333 */
6334
6335 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6336 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6337 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006338 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6339 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6340 init_server_map(curproxy);
6341 } else {
6342 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6343 fwrr_init_server_groups(curproxy);
6344 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006345 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006346
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006347 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006348 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6349 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6350 fwlc_init_server_tree(curproxy);
6351 } else {
6352 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6353 fas_init_server_tree(curproxy);
6354 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006355 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006356
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006357 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006358 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6359 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6360 chash_init_server_tree(curproxy);
6361 } else {
6362 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6363 init_server_map(curproxy);
6364 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006365 break;
6366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367
6368 if (curproxy->options & PR_O_LOGASAP)
6369 curproxy->to_log &= ~LW_BYTES;
6370
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006371 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006372 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006373 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6374 proxy_type_str(curproxy), curproxy->id);
6375 err_code |= ERR_WARN;
6376 }
6377
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006378 if (curproxy->mode != PR_MODE_HTTP) {
6379 int optnum;
6380
6381 if (curproxy->options & PR_O_COOK_ANY) {
6382 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6383 proxy_type_str(curproxy), curproxy->id);
6384 err_code |= ERR_WARN;
6385 }
6386
6387 if (curproxy->uri_auth) {
6388 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6389 proxy_type_str(curproxy), curproxy->id);
6390 err_code |= ERR_WARN;
6391 curproxy->uri_auth = NULL;
6392 }
6393
Willy Tarreau87cf5142011-08-19 22:57:24 +02006394 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006395 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6396 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6397 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006398 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006399 }
6400
6401 if (curproxy->options & PR_O_ORGTO) {
6402 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6403 "originalto", proxy_type_str(curproxy), curproxy->id);
6404 err_code |= ERR_WARN;
6405 curproxy->options &= ~PR_O_ORGTO;
6406 }
6407
6408 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6409 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6410 (curproxy->cap & cfg_opts[optnum].cap) &&
6411 (curproxy->options & cfg_opts[optnum].val)) {
6412 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6413 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6414 err_code |= ERR_WARN;
6415 curproxy->options &= ~cfg_opts[optnum].val;
6416 }
6417 }
6418
6419 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6420 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6421 (curproxy->cap & cfg_opts2[optnum].cap) &&
6422 (curproxy->options2 & cfg_opts2[optnum].val)) {
6423 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6424 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6425 err_code |= ERR_WARN;
6426 curproxy->options2 &= ~cfg_opts2[optnum].val;
6427 }
6428 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006429
Willy Tarreauefa5f512010-03-30 20:13:29 +02006430#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006431 if (curproxy->bind_hdr_occ) {
6432 curproxy->bind_hdr_occ = 0;
6433 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6434 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6435 err_code |= ERR_WARN;
6436 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006437#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006438 }
6439
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006441 * ensure that we're not cross-dressing a TCP server into HTTP.
6442 */
6443 newsrv = curproxy->srv;
6444 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006445 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006446 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6447 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006448 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006449 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006450
Willy Tarreau0cec3312011-10-31 13:49:26 +01006451 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6452 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6453 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6454 err_code |= ERR_WARN;
6455 }
6456
Willy Tarreauefa5f512010-03-30 20:13:29 +02006457#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006458 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6459 newsrv->bind_hdr_occ = 0;
6460 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6461 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6462 err_code |= ERR_WARN;
6463 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006464#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006465 newsrv = newsrv->next;
6466 }
6467
Willy Tarreauc1a21672009-08-16 22:37:44 +02006468 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006469 curproxy->accept = frontend_accept;
6470
Willy Tarreauc1a21672009-08-16 22:37:44 +02006471 if (curproxy->tcp_req.inspect_delay ||
6472 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006473 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006474
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006475 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006476 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006477 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006478 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006479
6480 /* both TCP and HTTP must check switching rules */
6481 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6482 }
6483
6484 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006485 if (curproxy->tcp_req.inspect_delay ||
6486 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6487 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6488
Emeric Brun97679e72010-09-23 17:56:44 +02006489 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6490 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6491
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006492 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006493 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006494 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006495 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006496
6497 /* If the backend does requires RDP cookie persistence, we have to
6498 * enable the corresponding analyser.
6499 */
6500 if (curproxy->options2 & PR_O2_RDPC_PRST)
6501 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6502 }
6503
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006504 listener = NULL;
6505 while (curproxy->listen) {
6506 struct listener *next;
6507
6508 next = curproxy->listen->next;
6509 curproxy->listen->next = listener;
6510 listener = curproxy->listen;
6511
6512 if (!next)
6513 break;
6514
6515 curproxy->listen = next;
6516 }
6517
Willy Tarreaue6b98942007-10-29 01:09:36 +01006518 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006519 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006520 listener = curproxy->listen;
6521 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006522 if (!listener->luid) {
6523 /* listener ID not set, use automatic numbering with first
6524 * spare entry starting with next_luid.
6525 */
6526 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6527 listener->conf.id.key = listener->luid = next_id;
6528 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006529 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006530 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006531
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006532 /* enable separate counters */
6533 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6534 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6535 if (!listener->name) {
6536 sprintf(trash, "sock-%d", listener->luid);
6537 listener->name = strdup(trash);
6538 }
6539 }
6540
Willy Tarreaue6b98942007-10-29 01:09:36 +01006541 if (curproxy->options & PR_O_TCP_NOLING)
6542 listener->options |= LI_O_NOLINGER;
6543 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006544 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006545 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006546 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006547 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006548 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006549 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006550
Willy Tarreau8a956912010-10-15 14:27:08 +02006551 if (listener->options & LI_O_ACC_PROXY)
6552 listener->analysers |= AN_REQ_DECODE_PROXY;
6553
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006554 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6555 listener->options |= LI_O_TCP_RULES;
6556
Willy Tarreaude3041d2010-05-31 10:56:17 +02006557 if (curproxy->mon_mask.s_addr)
6558 listener->options |= LI_O_CHK_MONNET;
6559
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006560 /* smart accept mode is automatic in HTTP mode */
6561 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6562 (curproxy->mode == PR_MODE_HTTP &&
6563 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6564 listener->options |= LI_O_NOQUICKACK;
6565
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006566 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006567 listener = listener->next;
6568 }
6569
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006570 /* Check multi-process mode compatibility for the current proxy */
6571 if (global.nbproc > 1) {
6572 int nbproc = 0;
6573 if (curproxy->bind_proc) {
6574 int proc;
6575 for (proc = 0; proc < global.nbproc; proc++) {
6576 if (curproxy->bind_proc & (1 << proc)) {
6577 nbproc++;
6578 }
6579 }
6580 } else {
6581 nbproc = global.nbproc;
6582 }
6583 if (curproxy->table.peers.name) {
6584 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6585 curproxy->id);
6586 cfgerr++;
6587 }
6588 if (nbproc > 1) {
6589 if (curproxy->uri_auth) {
6590 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6591 curproxy->id);
6592 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6593 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6594 curproxy->id);
6595 }
6596 }
6597 if (curproxy->appsession_name) {
6598 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6599 curproxy->id);
6600 }
6601 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6602 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6603 curproxy->id);
6604 }
6605 }
6606 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006607
6608 /* create the task associated with the proxy */
6609 curproxy->task = task_new();
6610 if (curproxy->task) {
6611 curproxy->task->context = curproxy;
6612 curproxy->task->process = manage_proxy;
6613 /* no need to queue, it will be done automatically if some
6614 * listener gets limited.
6615 */
6616 curproxy->task->expire = TICK_ETERNITY;
6617 } else {
6618 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6619 curproxy->id);
6620 cfgerr++;
6621 }
6622
Willy Tarreaubaaee002006-06-26 02:48:02 +02006623 curproxy = curproxy->next;
6624 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006625
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006626 /* Check multi-process mode compatibility */
6627 if (global.nbproc > 1) {
6628 if (global.stats_fe) {
6629 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6630 }
6631 }
6632
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006633 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6634 struct auth_users *curuser;
6635 int g;
6636
6637 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6638 unsigned int group_mask = 0;
6639 char *group = NULL;
6640
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006641 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006642 continue;
6643
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006644 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006645
6646 for (g = 0; g < curuserlist->grpcnt; g++)
6647 if (!strcmp(curuserlist->groups[g], group))
6648 break;
6649
6650 if (g == curuserlist->grpcnt) {
6651 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6652 curuserlist->name, group, curuser->user);
6653 err_code |= ERR_ALERT | ERR_FATAL;
6654 goto out;
6655 }
6656
6657 group_mask |= (1 << g);
6658 }
6659
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006660 free(curuser->u.groups);
6661 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006662 }
6663
6664 for (g = 0; g < curuserlist->grpcnt; g++) {
6665 char *user = NULL;
6666
6667 if (!curuserlist->groupusers[g])
6668 continue;
6669
6670 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6671 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6672 if (!strcmp(curuser->user, user))
6673 break;
6674
6675 if (!curuser) {
6676 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6677 curuserlist->name, user, curuserlist->groups[g]);
6678 err_code |= ERR_ALERT | ERR_FATAL;
6679 goto out;
6680 }
6681
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006682 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006683 }
6684
6685 free(curuserlist->groupusers[g]);
6686 }
6687
6688 free(curuserlist->groupusers);
6689
6690#ifdef DEBUG_AUTH
6691 for (g = 0; g < curuserlist->grpcnt; g++) {
6692 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6693
6694 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006695 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006696 fprintf(stderr, " %s", curuser->user);
6697 }
6698
6699 fprintf(stderr, "\n");
6700 }
6701#endif
6702
Willy Tarreaufbb78422011-06-05 15:38:35 +02006703 }
6704
6705 /* automatically compute fullconn if not set. We must not do it in the
6706 * loop above because cross-references are not yet fully resolved.
6707 */
6708 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6709 /* If <fullconn> is not set, let's set it to 10% of the sum of
6710 * the possible incoming frontend's maxconns.
6711 */
6712 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6713 struct proxy *fe;
6714 int total = 0;
6715
6716 /* sum up the number of maxconns of frontends which
6717 * reference this backend at least once or which are
6718 * the same one ('listen').
6719 */
6720 for (fe = proxy; fe; fe = fe->next) {
6721 struct switching_rule *rule;
6722 struct hdr_exp *exp;
6723 int found = 0;
6724
6725 if (!(fe->cap & PR_CAP_FE))
6726 continue;
6727
6728 if (fe == curproxy) /* we're on a "listen" instance */
6729 found = 1;
6730
6731 if (fe->defbe.be == curproxy) /* "default_backend" */
6732 found = 1;
6733
6734 /* check if a "use_backend" rule matches */
6735 if (!found) {
6736 list_for_each_entry(rule, &fe->switching_rules, list) {
6737 if (rule->be.backend == curproxy) {
6738 found = 1;
6739 break;
6740 }
6741 }
6742 }
6743
6744 /* check if a "reqsetbe" rule matches */
6745 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6746 if (exp->action == ACT_SETBE &&
6747 (struct proxy *)exp->replace == curproxy) {
6748 found = 1;
6749 break;
6750 }
6751 }
6752
6753 /* now we've checked all possible ways to reference a backend
6754 * from a frontend.
6755 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006756 if (!found)
6757 continue;
6758 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006759 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006760 /* we have the sum of the maxconns in <total>. We only
6761 * keep 10% of that sum to set the default fullconn, with
6762 * a hard minimum of 1 (to avoid a divide by zero).
6763 */
6764 curproxy->fullconn = (total + 9) / 10;
6765 if (!curproxy->fullconn)
6766 curproxy->fullconn = 1;
6767 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006768 }
6769
Willy Tarreau056f5682010-06-06 15:51:11 +02006770 /* initialize stick-tables on backend capable proxies. This must not
6771 * be done earlier because the data size may be discovered while parsing
6772 * other proxies.
6773 */
6774 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006775 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006776
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006777 /*
6778 * Recount currently required checks.
6779 */
6780
6781 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6782 int optnum;
6783
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006784 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6785 if (curproxy->options & cfg_opts[optnum].val)
6786 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006787
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006788 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6789 if (curproxy->options2 & cfg_opts2[optnum].val)
6790 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006791 }
6792
Willy Tarreau122541c2011-09-07 21:24:49 +02006793 if (peers) {
6794 struct peers *curpeers = peers, **last;
6795 struct peer *p, *pb;
6796
6797 /* Remove all peers sections which don't have a valid listener.
6798 * This can happen when a peers section is never referenced and
6799 * does not contain a local peer.
6800 */
6801 last = &peers;
6802 while (*last) {
6803 curpeers = *last;
6804 if (curpeers->peers_fe) {
6805 last = &curpeers->next;
6806 continue;
6807 }
6808
6809 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6810 curpeers->id, localpeer);
6811
6812 p = curpeers->remote;
6813 while (p) {
6814 pb = p->next;
6815 free(p->id);
6816 free(p);
6817 p = pb;
6818 }
6819
6820 /* Destroy and unlink this curpeers section.
6821 * Note: curpeers is backed up into *last.
6822 */
6823 free(curpeers->id);
6824 curpeers = curpeers->next;
6825 free(*last);
6826 *last = curpeers;
6827 }
6828 }
6829
Willy Tarreauac1932d2011-10-24 19:14:41 +02006830 if (!global.tune.max_http_hdr)
6831 global.tune.max_http_hdr = MAX_HTTP_HDR;
6832
Willy Tarreau34eb6712011-10-24 18:15:04 +02006833 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006834 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006835 MEM_F_SHARED);
6836
Willy Tarreaubb925012009-07-23 13:36:36 +02006837 if (cfgerr > 0)
6838 err_code |= ERR_ALERT | ERR_FATAL;
6839 out:
6840 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006841}
6842
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006843/*
6844 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6845 * parsing sessions.
6846 */
6847void cfg_register_keywords(struct cfg_kw_list *kwl)
6848{
6849 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6850}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006851
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006852/*
6853 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6854 */
6855void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6856{
6857 LIST_DEL(&kwl->list);
6858 LIST_INIT(&kwl->list);
6859}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006860
6861/*
6862 * Local variables:
6863 * c-indent-level: 8
6864 * c-basic-offset: 8
6865 * End:
6866 */