blob: 5d12056d05c1b3cf5f27c3d3794d8989066725e3 [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 Tarreau977b8e42006-12-29 14:19:17 +01001550 curproxy->source_addr = defproxy.source_addr;
1551 }
1552
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001554
1555 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001556 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001557 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001558 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001559 LIST_INIT(&node->list);
1560 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1561 }
1562
William Lallemand723b73a2012-02-08 16:37:49 +01001563 /* copy default log_format to curproxy */
1564 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1565 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1566 memcpy(node, tmplf, sizeof(struct logformat_node));
1567 LIST_INIT(&node->list);
1568 LIST_ADDQ(&curproxy->logformat, &node->list);
1569 }
1570
William Lallemanda73203e2012-03-12 12:48:57 +01001571 /* copy default unique_id to curproxy */
1572 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1573 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1574 memcpy(node, tmplf, sizeof(struct logformat_node));
1575 LIST_INIT(&node->list);
1576 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1577 }
1578
1579 /* copy default header unique id */
1580 if (defproxy.header_unique_id)
1581 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001584 curproxy->conf.used_listener_id = EB_ROOT;
1585 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001586
Willy Tarreau93893792009-07-23 13:19:11 +02001587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1590 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001591 /* FIXME-20070101: we should do this too at the end of the
1592 * config parsing to free all default values.
1593 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001594 free(defproxy.check_req);
1595 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001596 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001597 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001598 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001599 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001600 free(defproxy.capture_name);
1601 free(defproxy.monitor_uri);
1602 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001603 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001604 free(defproxy.fwdfor_hdr_name);
1605 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001606 free(defproxy.orgto_hdr_name);
1607 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001608 free(defproxy.server_id_hdr_name);
1609 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001610 free(defproxy.expect_str);
1611 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001612
Willy Tarreaua534fea2008-08-03 12:19:50 +02001613 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001614 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001615
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 /* we cannot free uri_auth because it might already be used */
1617 init_default_instance();
1618 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 }
1622 else if (curproxy == NULL) {
1623 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001624 err_code |= ERR_ALERT | ERR_FATAL;
1625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 }
1627
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628
1629 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001631 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001632 int cur_arg;
1633
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (curproxy == &defproxy) {
1635 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641
Emeric Bruned760922010-10-22 17:59:25 +02001642 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001643 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001648
1649 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001650
1651 /* NOTE: the following line might create several listeners if there
1652 * are comma-separated IPs or port ranges. So all further processing
1653 * will have to be applied to all listeners created after last_listen.
1654 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001655 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
1658 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001659
Willy Tarreau90a570f2009-10-04 20:54:54 +02001660 new_listen = curproxy->listen;
1661 while (new_listen != last_listen) {
1662 new_listen->conf.file = file;
1663 new_listen->conf.line = linenum;
1664 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001665 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001666 }
1667
Emeric Bruned760922010-10-22 17:59:25 +02001668 /* Set default global rights and owner for unix bind */
1669 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1670 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1671 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001672 cur_arg = 2;
1673 while (*(args[cur_arg])) {
1674 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1675#ifdef SO_BINDTODEVICE
1676 struct listener *l;
1677
Emeric Bruned760922010-10-22 17:59:25 +02001678 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1679 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1680 file, linenum, args[0], args[cur_arg]);
1681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
1683 }
1684
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001685 if (!*args[cur_arg + 1]) {
1686 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001690 }
1691
1692 for (l = curproxy->listen; l != last_listen; l = l->next)
1693 l->interface = strdup(args[cur_arg + 1]);
1694
1695 global.last_checks |= LSTCHK_NETADM;
1696
1697 cur_arg += 2;
1698 continue;
1699#else
1700 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1701 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001704#endif
1705 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001706 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1707#ifdef TCP_MAXSEG
1708 struct listener *l;
1709 int mss;
1710
Emeric Bruned760922010-10-22 17:59:25 +02001711 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1712 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1713 file, linenum, args[0], args[cur_arg]);
1714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
1716 }
1717
Willy Tarreaube1b9182009-06-14 18:48:19 +02001718 if (!*args[cur_arg + 1]) {
1719 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001723 }
1724
Willy Tarreau48a7e722010-12-24 15:26:39 +01001725 mss = atoi(args[cur_arg + 1]);
1726 if (!mss || abs(mss) > 65535) {
1727 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001731 }
1732
1733 for (l = curproxy->listen; l != last_listen; l = l->next)
1734 l->maxseg = mss;
1735
1736 cur_arg += 2;
1737 continue;
1738#else
1739 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1740 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001743#endif
1744 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001745
1746 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1747#ifdef TCP_DEFER_ACCEPT
1748 struct listener *l;
1749
1750 for (l = curproxy->listen; l != last_listen; l = l->next)
1751 l->options |= LI_O_DEF_ACCEPT;
1752
1753 cur_arg ++;
1754 continue;
1755#else
1756 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1757 file, linenum, args[0], args[cur_arg]);
1758 err_code |= ERR_ALERT | ERR_FATAL;
1759 goto out;
1760#endif
1761 }
1762
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001763 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001764#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001765 struct listener *l;
1766
Emeric Bruned760922010-10-22 17:59:25 +02001767 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1768 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1769 file, linenum, args[0], args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001774 for (l = curproxy->listen; l != last_listen; l = l->next)
1775 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001776
1777 cur_arg ++;
1778 continue;
1779#else
1780 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1781 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001784#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001785 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001786
Willy Tarreau8a956912010-10-15 14:27:08 +02001787 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1788 struct listener *l;
1789
1790 for (l = curproxy->listen; l != last_listen; l = l->next)
1791 l->options |= LI_O_ACC_PROXY;
1792
1793 cur_arg ++;
1794 continue;
1795 }
1796
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001797 if (!strcmp(args[cur_arg], "name")) {
1798 struct listener *l;
1799
1800 for (l = curproxy->listen; l != last_listen; l = l->next)
1801 l->name = strdup(args[cur_arg + 1]);
1802
1803 cur_arg += 2;
1804 continue;
1805 }
1806
1807 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001808 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001809 struct listener *l;
1810
1811 if (curproxy->listen->next != last_listen) {
1812 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1813 file, linenum, args[cur_arg]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 if (!*args[cur_arg + 1]) {
1819 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1820 file, linenum, args[cur_arg]);
1821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
1824
1825 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001826 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001827
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001828 if (curproxy->listen->luid <= 0) {
1829 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001830 file, linenum);
1831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
1833 }
1834
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001835 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1836 if (node) {
1837 l = container_of(node, struct listener, conf.id);
1838 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1839 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1844
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001845 cur_arg += 2;
1846 continue;
1847 }
1848
Emeric Bruned760922010-10-22 17:59:25 +02001849 if (!strcmp(args[cur_arg], "mode")) {
1850
1851 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1853 file, linenum, args[0], args[cur_arg]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1859
1860 cur_arg += 2;
1861 continue;
1862 }
1863
1864 if (!strcmp(args[cur_arg], "uid")) {
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872
1873 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1874 cur_arg += 2;
1875 continue;
1876 }
1877
1878 if (!strcmp(args[cur_arg], "gid")) {
1879
1880 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1881 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1882 file, linenum, args[0], args[cur_arg]);
1883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
1885 }
1886
1887 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1888 cur_arg += 2;
1889 continue;
1890 }
1891
1892 if (!strcmp(args[cur_arg], "user")) {
1893 struct passwd *user;
1894
1895 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1896 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1897 file, linenum, args[0], args[cur_arg]);
1898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
1900 }
1901 user = getpwnam(args[cur_arg + 1]);
1902 if (!user) {
1903 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1904 file, linenum, args[0], args[cur_arg + 1 ]);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908
1909 curproxy->listen->perm.ux.uid = user->pw_uid;
1910 cur_arg += 2;
1911 continue;
1912 }
1913
1914 if (!strcmp(args[cur_arg], "group")) {
1915 struct group *group;
1916
1917 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1918 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1919 file, linenum, args[0], args[cur_arg]);
1920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
1922 }
1923 group = getgrnam(args[cur_arg + 1]);
1924 if (!group) {
1925 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1926 file, linenum, args[0], args[cur_arg + 1 ]);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930
1931 curproxy->listen->perm.ux.gid = group->gr_gid;
1932 cur_arg += 2;
1933 continue;
1934 }
1935
Willy Tarreaub48f9582011-09-05 01:17:06 +02001936 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 +01001937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001940 }
Willy Tarreau93893792009-07-23 13:19:11 +02001941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 }
1943 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1944 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1945 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001950 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001952
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 /* flush useless bits */
1954 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001957 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960
Willy Tarreau1c47f852006-07-09 08:22:27 +02001961 if (!*args[1]) {
1962 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1963 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001964 err_code |= ERR_ALERT | ERR_FATAL;
1965 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001966 }
1967
Willy Tarreaua534fea2008-08-03 12:19:50 +02001968 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001969 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001970 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001971 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001972 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1973
Willy Tarreau93893792009-07-23 13:19:11 +02001974 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1977 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1978 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1979 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1980 else {
1981 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 }
1985 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001986 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001987 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001988
1989 if (curproxy == &defproxy) {
1990 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 }
1995
1996 if (!*args[1]) {
1997 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1998 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002001 }
2002
2003 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002004 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002005
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002006 if (curproxy->uuid <= 0) {
2007 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002008 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_ALERT | ERR_FATAL;
2010 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002011 }
2012
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002013 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2014 if (node) {
2015 struct proxy *target = container_of(node, struct proxy, conf.id);
2016 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2017 file, linenum, proxy_type_str(curproxy), curproxy->id,
2018 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
2021 }
2022 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002023 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002024 else if (!strcmp(args[0], "description")) {
2025 int i, len=0;
2026 char *d;
2027
Cyril Bonté99ed3272010-01-24 23:29:44 +01002028 if (curproxy == &defproxy) {
2029 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2030 file, linenum, args[0]);
2031 err_code |= ERR_ALERT | ERR_FATAL;
2032 goto out;
2033 }
2034
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002035 if (!*args[1]) {
2036 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2037 file, linenum, args[0]);
2038 return -1;
2039 }
2040
2041 for(i=1; *args[i]; i++)
2042 len += strlen(args[i])+1;
2043
2044 d = (char *)calloc(1, len);
2045 curproxy->desc = d;
2046
2047 d += sprintf(d, "%s", args[1]);
2048 for(i=2; *args[i]; i++)
2049 d += sprintf(d, " %s", args[i]);
2050
2051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2053 curproxy->state = PR_STSTOPPED;
2054 }
2055 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2056 curproxy->state = PR_STNEW;
2057 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002058 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2059 int cur_arg = 1;
2060 unsigned int set = 0;
2061
2062 while (*args[cur_arg]) {
2063 int u;
2064 if (strcmp(args[cur_arg], "all") == 0) {
2065 set = 0;
2066 break;
2067 }
2068 else if (strcmp(args[cur_arg], "odd") == 0) {
2069 set |= 0x55555555;
2070 }
2071 else if (strcmp(args[cur_arg], "even") == 0) {
2072 set |= 0xAAAAAAAA;
2073 }
2074 else {
2075 u = str2uic(args[cur_arg]);
2076 if (u < 1 || u > 32) {
2077 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2078 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002081 }
2082 if (u > global.nbproc) {
2083 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002086 }
2087 set |= 1 << (u - 1);
2088 }
2089 cur_arg++;
2090 }
2091 curproxy->bind_proc = set;
2092 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002093 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002094 if (curproxy == &defproxy) {
2095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002098 }
2099
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002100 err = invalid_char(args[1]);
2101 if (err) {
2102 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2103 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002105 }
2106
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002107 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2108 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2109 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002112 }
2113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2115 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116
Willy Tarreau977b8e42006-12-29 14:19:17 +01002117 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002119
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 if (*(args[1]) == 0) {
2121 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002126
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002127 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002128 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002129 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002130 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002131 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 curproxy->cookie_name = strdup(args[1]);
2133 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002134
Willy Tarreaubaaee002006-06-26 02:48:02 +02002135 cur_arg = 2;
2136 while (*(args[cur_arg])) {
2137 if (!strcmp(args[cur_arg], "rewrite")) {
2138 curproxy->options |= PR_O_COOK_RW;
2139 }
2140 else if (!strcmp(args[cur_arg], "indirect")) {
2141 curproxy->options |= PR_O_COOK_IND;
2142 }
2143 else if (!strcmp(args[cur_arg], "insert")) {
2144 curproxy->options |= PR_O_COOK_INS;
2145 }
2146 else if (!strcmp(args[cur_arg], "nocache")) {
2147 curproxy->options |= PR_O_COOK_NOC;
2148 }
2149 else if (!strcmp(args[cur_arg], "postonly")) {
2150 curproxy->options |= PR_O_COOK_POST;
2151 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002152 else if (!strcmp(args[cur_arg], "preserve")) {
2153 curproxy->options2 |= PR_O2_COOK_PSV;
2154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 else if (!strcmp(args[cur_arg], "prefix")) {
2156 curproxy->options |= PR_O_COOK_PFX;
2157 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002158 else if (!strcmp(args[cur_arg], "domain")) {
2159 if (!*args[cur_arg + 1]) {
2160 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2161 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002164 }
2165
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002166 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002167 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002168 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2169 " dots nor does not start with a dot."
2170 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002171 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002172 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002173 }
2174
2175 err = invalid_domainchar(args[cur_arg + 1]);
2176 if (err) {
2177 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2178 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002181 }
2182
Willy Tarreau68a897b2009-12-03 23:28:34 +01002183 if (!curproxy->cookie_domain) {
2184 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2185 } else {
2186 /* one domain was already specified, add another one by
2187 * building the string which will be returned along with
2188 * the cookie.
2189 */
2190 char *new_ptr;
2191 int new_len = strlen(curproxy->cookie_domain) +
2192 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2193 new_ptr = malloc(new_len);
2194 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2195 free(curproxy->cookie_domain);
2196 curproxy->cookie_domain = new_ptr;
2197 }
Willy Tarreau31936852010-10-06 16:59:56 +02002198 cur_arg++;
2199 }
2200 else if (!strcmp(args[cur_arg], "maxidle")) {
2201 unsigned int maxidle;
2202 const char *res;
2203
2204 if (!*args[cur_arg + 1]) {
2205 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2206 file, linenum, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210
2211 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2212 if (res) {
2213 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2214 file, linenum, *res, args[cur_arg]);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218 curproxy->cookie_maxidle = maxidle;
2219 cur_arg++;
2220 }
2221 else if (!strcmp(args[cur_arg], "maxlife")) {
2222 unsigned int maxlife;
2223 const char *res;
2224
2225 if (!*args[cur_arg + 1]) {
2226 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2227 file, linenum, args[cur_arg]);
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231
2232 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2233 if (res) {
2234 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2235 file, linenum, *res, args[cur_arg]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002240 cur_arg++;
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002243 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 +02002244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
2248 cur_arg++;
2249 }
2250 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2251 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 }
2255
2256 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2257 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002261
2262 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2263 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2264 file, linenum);
2265 err_code |= ERR_ALERT | ERR_FATAL;
2266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002268 else if (!strcmp(args[0], "persist")) { /* persist */
2269 if (*(args[1]) == 0) {
2270 Alert("parsing [%s:%d] : missing persist method.\n",
2271 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002274 }
2275
2276 if (!strncmp(args[1], "rdp-cookie", 10)) {
2277 curproxy->options2 |= PR_O2_RDPC_PRST;
2278
Emeric Brunb982a3d2010-01-04 15:45:53 +01002279 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002280 const char *beg, *end;
2281
2282 beg = args[1] + 11;
2283 end = strchr(beg, ')');
2284
2285 if (!end || end == beg) {
2286 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2287 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002290 }
2291
2292 free(curproxy->rdp_cookie_name);
2293 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2294 curproxy->rdp_cookie_len = end-beg;
2295 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002296 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002297 free(curproxy->rdp_cookie_name);
2298 curproxy->rdp_cookie_name = strdup("msts");
2299 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2300 }
2301 else { /* syntax */
2302 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2303 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002306 }
2307 }
2308 else {
2309 Alert("parsing [%s:%d] : unknown persist method.\n",
2310 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002313 }
2314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002316 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002318 if (curproxy == &defproxy) {
2319 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2320 err_code |= ERR_ALERT | ERR_FATAL;
2321 goto out;
2322 }
2323
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002326
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002328 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 }
2333 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002334 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 curproxy->appsession_name = strdup(args[1]);
2336 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2337 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002338 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2339 if (err) {
2340 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2341 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002344 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002345 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002346
Willy Tarreau51041c72007-09-09 21:56:53 +02002347 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_ABORT;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002352
2353 cur_arg = 6;
2354 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002355 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2356 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002357 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002358 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002359 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002360 } else if (!strcmp(args[cur_arg], "prefix")) {
2361 curproxy->options2 |= PR_O2_AS_PFX;
2362 } else if (!strcmp(args[cur_arg], "mode")) {
2363 if (!*args[cur_arg + 1]) {
2364 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2365 file, linenum, args[0], args[cur_arg]);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
2368 }
2369
2370 cur_arg++;
2371 if (!strcmp(args[cur_arg], "query-string")) {
2372 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2373 curproxy->options2 |= PR_O2_AS_M_QS;
2374 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2375 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2376 curproxy->options2 |= PR_O2_AS_M_PP;
2377 } else {
2378 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
2382 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002383 cur_arg++;
2384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 } /* Url App Session */
2386 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002387 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002391 if (curproxy == &defproxy) {
2392 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
2395 }
2396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (*(args[4]) == 0) {
2398 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002403 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 curproxy->capture_name = strdup(args[2]);
2405 curproxy->capture_namelen = strlen(curproxy->capture_name);
2406 curproxy->capture_len = atol(args[4]);
2407 if (curproxy->capture_len >= CAPTURE_LEN) {
2408 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2409 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 curproxy->capture_len = CAPTURE_LEN - 1;
2412 }
2413 curproxy->to_log |= LW_COOKIE;
2414 }
2415 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2416 struct cap_hdr *hdr;
2417
2418 if (curproxy == &defproxy) {
2419 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 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 }
2423
2424 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2425 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2426 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430
2431 hdr = calloc(sizeof(struct cap_hdr), 1);
2432 hdr->next = curproxy->req_cap;
2433 hdr->name = strdup(args[3]);
2434 hdr->namelen = strlen(args[3]);
2435 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002436 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 hdr->index = curproxy->nb_req_cap++;
2438 curproxy->req_cap = hdr;
2439 curproxy->to_log |= LW_REQHDR;
2440 }
2441 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2442 struct cap_hdr *hdr;
2443
2444 if (curproxy == &defproxy) {
2445 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 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
2449
2450 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2451 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2452 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 hdr = calloc(sizeof(struct cap_hdr), 1);
2457 hdr->next = curproxy->rsp_cap;
2458 hdr->name = strdup(args[3]);
2459 hdr->namelen = strlen(args[3]);
2460 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002461 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 hdr->index = curproxy->nb_rsp_cap++;
2463 curproxy->rsp_cap = hdr;
2464 curproxy->to_log |= LW_RSPHDR;
2465 }
2466 else {
2467 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 }
2472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002474 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002476
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 if (*(args[1]) == 0) {
2478 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2479 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002482 }
2483 curproxy->conn_retries = atol(args[1]);
2484 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002485 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002486 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002487
2488 if (curproxy == &defproxy) {
2489 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493
Willy Tarreauff011f22011-01-06 17:51:27 +01002494 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 +01002495 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2496 file, linenum, args[0]);
2497 err_code |= ERR_WARN;
2498 }
2499
Willy Tarreauff011f22011-01-06 17:51:27 +01002500 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002501
Willy Tarreauff011f22011-01-06 17:51:27 +01002502 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002503 err_code |= ERR_ALERT | ERR_ABORT;
2504 goto out;
2505 }
2506
Willy Tarreauff011f22011-01-06 17:51:27 +01002507 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2508 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002509 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002510 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2511 /* set the header name and length into the proxy structure */
2512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2513 err_code |= ERR_WARN;
2514
2515 if (!*args[1]) {
2516 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2517 file, linenum, args[0]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521
2522 /* set the desired header name */
2523 free(curproxy->server_id_hdr_name);
2524 curproxy->server_id_hdr_name = strdup(args[1]);
2525 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2526 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002527 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002528 if (curproxy == &defproxy) {
2529 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002532 }
2533
Willy Tarreauef6494c2010-01-28 17:12:36 +01002534 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002535 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002539 }
2540
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002541 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2542 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2543 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002546 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002547
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002548 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002549 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002550 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002551 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002552 struct redirect_rule *rule;
2553 int cur_arg;
2554 int type = REDIRECT_TYPE_NONE;
2555 int code = 302;
2556 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002557 char *cookie = NULL;
2558 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002559 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002560
Cyril Bonté99ed3272010-01-24 23:29:44 +01002561 if (curproxy == &defproxy) {
2562 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
2565 }
2566
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002567 cur_arg = 1;
2568 while (*(args[cur_arg])) {
2569 if (!strcmp(args[cur_arg], "location")) {
2570 if (!*args[cur_arg + 1]) {
2571 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2572 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002575 }
2576
2577 type = REDIRECT_TYPE_LOCATION;
2578 cur_arg++;
2579 destination = args[cur_arg];
2580 }
2581 else if (!strcmp(args[cur_arg], "prefix")) {
2582 if (!*args[cur_arg + 1]) {
2583 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 }
2588
2589 type = REDIRECT_TYPE_PREFIX;
2590 cur_arg++;
2591 destination = args[cur_arg];
2592 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002593 else if (!strcmp(args[cur_arg], "set-cookie")) {
2594 if (!*args[cur_arg + 1]) {
2595 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2596 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002599 }
2600
2601 cur_arg++;
2602 cookie = args[cur_arg];
2603 cookie_set = 1;
2604 }
2605 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2606 if (!*args[cur_arg + 1]) {
2607 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2608 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002611 }
2612
2613 cur_arg++;
2614 cookie = args[cur_arg];
2615 cookie_set = 0;
2616 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 else if (!strcmp(args[cur_arg],"code")) {
2618 if (!*args[cur_arg + 1]) {
2619 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2620 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002623 }
2624 cur_arg++;
2625 code = atol(args[cur_arg]);
2626 if (code < 301 || code > 303) {
2627 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2628 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002631 }
2632 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002633 else if (!strcmp(args[cur_arg],"drop-query")) {
2634 flags |= REDIRECT_FLAG_DROP_QS;
2635 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002636 else if (!strcmp(args[cur_arg],"append-slash")) {
2637 flags |= REDIRECT_FLAG_APPEND_SLASH;
2638 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002639 else if (strcmp(args[cur_arg], "if") == 0 ||
2640 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002641 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002642 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002643 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2644 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 break;
2649 }
2650 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002651 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 +02002652 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002655 }
2656 cur_arg++;
2657 }
2658
2659 if (type == REDIRECT_TYPE_NONE) {
2660 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2661 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 }
2665
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002666 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2667 rule->cond = cond;
2668 rule->rdr_str = strdup(destination);
2669 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002670 if (cookie) {
2671 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002672 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002673 */
2674 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002675 if (cookie_set) {
2676 rule->cookie_str = malloc(rule->cookie_len + 10);
2677 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2678 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2679 rule->cookie_len += 9;
2680 } else {
2681 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002682 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002683 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2684 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002685 }
2686 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002687 rule->type = type;
2688 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002689 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002690 LIST_INIT(&rule->list);
2691 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002692 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2693 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002694 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002695 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002696 struct switching_rule *rule;
2697
Willy Tarreaub099aca2008-10-12 17:26:37 +02002698 if (curproxy == &defproxy) {
2699 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002702 }
2703
Willy Tarreau55ea7572007-06-17 19:56:27 +02002704 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002706
2707 if (*(args[1]) == 0) {
2708 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002711 }
2712
Willy Tarreauef6494c2010-01-28 17:12:36 +01002713 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002718 }
2719
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002720 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2721 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2722 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002725 }
2726
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002727 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002728
Willy Tarreau55ea7572007-06-17 19:56:27 +02002729 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2730 rule->cond = cond;
2731 rule->be.name = strdup(args[1]);
2732 LIST_INIT(&rule->list);
2733 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2734 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002735 else if (strcmp(args[0], "use-server") == 0) {
2736 struct server_rule *rule;
2737
2738 if (curproxy == &defproxy) {
2739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
2742 }
2743
2744 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2745 err_code |= ERR_WARN;
2746
2747 if (*(args[1]) == 0) {
2748 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752
2753 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2754 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2755 file, linenum, args[0]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
2759
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002760 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2761 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2762 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766
2767 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2768
2769 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2770 rule->cond = cond;
2771 rule->srv.name = strdup(args[1]);
2772 LIST_INIT(&rule->list);
2773 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2774 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2775 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002776 else if ((!strcmp(args[0], "force-persist")) ||
2777 (!strcmp(args[0], "ignore-persist"))) {
2778 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002779
2780 if (curproxy == &defproxy) {
2781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785
2786 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2787 err_code |= ERR_WARN;
2788
Willy Tarreauef6494c2010-01-28 17:12:36 +01002789 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002790 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2791 file, linenum, args[0]);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002796 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2797 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2798 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002803 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002804
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002805 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002806 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002807 if (!strcmp(args[0], "force-persist")) {
2808 rule->type = PERSIST_TYPE_FORCE;
2809 } else {
2810 rule->type = PERSIST_TYPE_IGNORE;
2811 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002812 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002813 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002814 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002815 else if (!strcmp(args[0], "stick-table")) {
2816 int myidx = 1;
2817
Emeric Brun32da3c42010-09-23 18:39:19 +02002818 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002819 curproxy->table.type = (unsigned int)-1;
2820 while (*args[myidx]) {
2821 const char *err;
2822
2823 if (strcmp(args[myidx], "size") == 0) {
2824 myidx++;
2825 if (!*(args[myidx])) {
2826 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2827 file, linenum, args[myidx-1]);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2832 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2833 file, linenum, *err, args[myidx-1]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002837 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002838 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002839 else if (strcmp(args[myidx], "peers") == 0) {
2840 myidx++;
2841 if (!*(args[myidx])) {
2842 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2843 file, linenum, args[myidx-1]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847 curproxy->table.peers.name = strdup(args[myidx++]);
2848 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002849 else if (strcmp(args[myidx], "expire") == 0) {
2850 myidx++;
2851 if (!*(args[myidx])) {
2852 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2853 file, linenum, args[myidx-1]);
2854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2858 if (err) {
2859 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2860 file, linenum, *err, args[myidx-1]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002865 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 }
2867 else if (strcmp(args[myidx], "nopurge") == 0) {
2868 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002869 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002870 }
2871 else if (strcmp(args[myidx], "type") == 0) {
2872 myidx++;
2873 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2874 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2875 file, linenum, args[myidx]);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002879 /* myidx already points to next arg */
2880 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002881 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002882 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002883 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002884
2885 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002886 nw = args[myidx];
2887 while (*nw) {
2888 /* the "store" keyword supports a comma-separated list */
2889 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002890 sa = NULL; /* store arg */
2891 while (*nw && *nw != ',') {
2892 if (*nw == '(') {
2893 *nw = 0;
2894 sa = ++nw;
2895 while (*nw != ')') {
2896 if (!*nw) {
2897 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2898 file, linenum, args[0], cw);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
2902 nw++;
2903 }
2904 *nw = '\0';
2905 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002906 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002907 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002908 if (*nw)
2909 *nw++ = '\0';
2910 type = stktable_get_data_type(cw);
2911 if (type < 0) {
2912 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2913 file, linenum, args[0], cw);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
Willy Tarreauac782882010-06-20 10:41:54 +02002917
2918 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2919 switch (err) {
2920 case PE_NONE: break;
2921 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002922 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2923 file, linenum, args[0], cw);
2924 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002925 break;
2926
2927 case PE_ARG_MISSING:
2928 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2929 file, linenum, args[0], cw);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932
2933 case PE_ARG_NOT_USED:
2934 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2935 file, linenum, args[0], cw);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938
2939 default:
2940 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2941 file, linenum, args[0], cw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002944 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002945 }
2946 myidx++;
2947 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002948 else {
2949 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2950 file, linenum, args[myidx]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 }
2955
2956 if (!curproxy->table.size) {
2957 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2958 file, linenum);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962
2963 if (curproxy->table.type == (unsigned int)-1) {
2964 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2965 file, linenum);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
2969 }
2970 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002972 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002973 int myidx = 0;
2974 const char *name = NULL;
2975 int flags;
2976
2977 if (curproxy == &defproxy) {
2978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2984 err_code |= ERR_WARN;
2985 goto out;
2986 }
2987
2988 myidx++;
2989 if ((strcmp(args[myidx], "store") == 0) ||
2990 (strcmp(args[myidx], "store-request") == 0)) {
2991 myidx++;
2992 flags = STK_IS_STORE;
2993 }
2994 else if (strcmp(args[myidx], "store-response") == 0) {
2995 myidx++;
2996 flags = STK_IS_STORE | STK_ON_RSP;
2997 }
2998 else if (strcmp(args[myidx], "match") == 0) {
2999 myidx++;
3000 flags = STK_IS_MATCH;
3001 }
3002 else if (strcmp(args[myidx], "on") == 0) {
3003 myidx++;
3004 flags = STK_IS_MATCH | STK_IS_STORE;
3005 }
3006 else {
3007 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011
3012 if (*(args[myidx]) == 0) {
3013 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
3017
Willy Tarreau12785782012-04-27 21:37:17 +02003018 expr = sample_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003020 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
3025 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003026 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3028 file, linenum, args[0], expr->fetch->kw);
3029 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003030 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 goto out;
3032 }
3033 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003034 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3036 file, linenum, args[0], expr->fetch->kw);
3037 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003038 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 goto out;
3040 }
3041 }
3042
3043 if (strcmp(args[myidx], "table") == 0) {
3044 myidx++;
3045 name = args[myidx++];
3046 }
3047
Willy Tarreauef6494c2010-01-28 17:12:36 +01003048 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003049 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3050 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3051 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003052 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003053 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003054 goto out;
3055 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003056 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003057 else if (*(args[myidx])) {
3058 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3059 file, linenum, args[0], args[myidx]);
3060 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003061 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003062 goto out;
3063 }
Emeric Brun97679e72010-09-23 17:56:44 +02003064 if (flags & STK_ON_RSP)
3065 err_code |= warnif_cond_requires_req(cond, file, linenum);
3066 else
3067 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003068
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3070 rule->cond = cond;
3071 rule->expr = expr;
3072 rule->flags = flags;
3073 rule->table.name = name ? strdup(name) : NULL;
3074 LIST_INIT(&rule->list);
3075 if (flags & STK_ON_RSP)
3076 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3077 else
3078 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003081 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003083
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3085 curproxy->uri_auth = NULL; /* we must detach from the default config */
3086
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003087 if (!*args[1]) {
3088 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003089 } else if (!strcmp(args[1], "admin")) {
3090 struct stats_admin_rule *rule;
3091
3092 if (curproxy == &defproxy) {
3093 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097
3098 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3099 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
3102 }
3103
3104 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3105 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3106 file, linenum, args[0], args[1]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003110 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3111 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3112 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3118
3119 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3120 rule->cond = cond;
3121 LIST_INIT(&rule->list);
3122 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 } else if (!strcmp(args[1], "uri")) {
3124 if (*(args[2]) == 0) {
3125 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3129 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_ABORT;
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
3133 } else if (!strcmp(args[1], "realm")) {
3134 if (*(args[2]) == 0) {
3135 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3139 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_ABORT;
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003143 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003144 unsigned interval;
3145
3146 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3147 if (err) {
3148 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3149 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003152 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_ABORT;
3155 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003156 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003157 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003158 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003159
3160 if (curproxy == &defproxy) {
3161 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165
3166 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3167 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3168 err_code |= ERR_ALERT | ERR_ABORT;
3169 goto out;
3170 }
3171
Willy Tarreauff011f22011-01-06 17:51:27 +01003172 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3173 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003174 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3175 file, linenum, args[0]);
3176 err_code |= ERR_WARN;
3177 }
3178
Willy Tarreauff011f22011-01-06 17:51:27 +01003179 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003180
Willy Tarreauff011f22011-01-06 17:51:27 +01003181 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003182 err_code |= ERR_ALERT | ERR_ABORT;
3183 goto out;
3184 }
3185
Willy Tarreauff011f22011-01-06 17:51:27 +01003186 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3187 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003188
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 } else if (!strcmp(args[1], "auth")) {
3190 if (*(args[2]) == 0) {
3191 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3195 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 } else if (!strcmp(args[1], "scope")) {
3200 if (*(args[2]) == 0) {
3201 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209 } else if (!strcmp(args[1], "enable")) {
3210 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3211 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003212 err_code |= ERR_ALERT | ERR_ABORT;
3213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003214 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003215 } else if (!strcmp(args[1], "hide-version")) {
3216 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003218 err_code |= ERR_ALERT | ERR_ABORT;
3219 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003220 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003221 } else if (!strcmp(args[1], "show-legends")) {
3222 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3223 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3224 err_code |= ERR_ALERT | ERR_ABORT;
3225 goto out;
3226 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003227 } else if (!strcmp(args[1], "show-node")) {
3228
3229 if (*args[2]) {
3230 int i;
3231 char c;
3232
3233 for (i=0; args[2][i]; i++) {
3234 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003235 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3236 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003237 break;
3238 }
3239
3240 if (!i || args[2][i]) {
3241 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3242 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3243 file, linenum, args[0], args[1]);
3244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
3246 }
3247 }
3248
3249 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3250 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3251 err_code |= ERR_ALERT | ERR_ABORT;
3252 goto out;
3253 }
3254 } else if (!strcmp(args[1], "show-desc")) {
3255 char *desc = NULL;
3256
3257 if (*args[2]) {
3258 int i, len=0;
3259 char *d;
3260
3261 for(i=2; *args[i]; i++)
3262 len += strlen(args[i])+1;
3263
3264 desc = d = (char *)calloc(1, len);
3265
3266 d += sprintf(d, "%s", args[2]);
3267 for(i=3; *args[i]; i++)
3268 d += sprintf(d, " %s", args[i]);
3269 }
3270
3271 if (!*args[2] && !global.desc)
3272 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3273 file, linenum, args[1]);
3274 else {
3275 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3276 free(desc);
3277 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3278 err_code |= ERR_ALERT | ERR_ABORT;
3279 goto out;
3280 }
3281 free(desc);
3282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003284stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003285 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 +01003286 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
3290 }
3291 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003292 int optnum;
3293
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003294 if (*(args[1]) == '\0') {
3295 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3296 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003300
3301 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3302 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003303 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3304 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3305 file, linenum, cfg_opts[optnum].name);
3306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
Willy Tarreau93893792009-07-23 13:19:11 +02003309 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3310 err_code |= ERR_WARN;
3311 goto out;
3312 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003313
Willy Tarreau3842f002009-06-14 11:39:52 +02003314 curproxy->no_options &= ~cfg_opts[optnum].val;
3315 curproxy->options &= ~cfg_opts[optnum].val;
3316
3317 switch (kwm) {
3318 case KWM_STD:
3319 curproxy->options |= cfg_opts[optnum].val;
3320 break;
3321 case KWM_NO:
3322 curproxy->no_options |= cfg_opts[optnum].val;
3323 break;
3324 case KWM_DEF: /* already cleared */
3325 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003326 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003327
Willy Tarreau93893792009-07-23 13:19:11 +02003328 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003329 }
3330 }
3331
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003332 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3333 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003334 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3335 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3336 file, linenum, cfg_opts2[optnum].name);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
Willy Tarreau93893792009-07-23 13:19:11 +02003340 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3341 err_code |= ERR_WARN;
3342 goto out;
3343 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003344
Willy Tarreau3842f002009-06-14 11:39:52 +02003345 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3346 curproxy->options2 &= ~cfg_opts2[optnum].val;
3347
3348 switch (kwm) {
3349 case KWM_STD:
3350 curproxy->options2 |= cfg_opts2[optnum].val;
3351 break;
3352 case KWM_NO:
3353 curproxy->no_options2 |= cfg_opts2[optnum].val;
3354 break;
3355 case KWM_DEF: /* already cleared */
3356 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003357 }
Willy Tarreau93893792009-07-23 13:19:11 +02003358 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003359 }
3360 }
3361
Willy Tarreau3842f002009-06-14 11:39:52 +02003362 if (kwm != KWM_STD) {
3363 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003364 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003367 }
3368
Emeric Brun3a058f32009-06-30 18:26:00 +02003369 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003370 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003372 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003373 if (*(args[2]) != '\0') {
3374 if (!strcmp(args[2], "clf")) {
3375 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003376 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003377 } else {
3378 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003381 }
3382 }
William Lallemand1d705562012-03-12 12:46:41 +01003383 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003385 else if (!strcmp(args[1], "tcplog")) {
3386 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003388 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003389 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 else if (!strcmp(args[1], "tcpka")) {
3392 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003393 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003395
3396 if (curproxy->cap & PR_CAP_FE)
3397 curproxy->options |= PR_O_TCP_CLI_KA;
3398 if (curproxy->cap & PR_CAP_BE)
3399 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
3401 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003402 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_WARN;
3404
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003406 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003407 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003408 curproxy->options2 &= ~PR_O2_CHK_ANY;
3409 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 if (!*args[2]) { /* no argument */
3411 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3412 curproxy->check_len = strlen(DEF_CHECK_REQ);
3413 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003414 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 curproxy->check_req = (char *)malloc(reqlen);
3416 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003417 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003419 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 if (*args[4])
3421 reqlen += strlen(args[4]);
3422 else
3423 reqlen += strlen("HTTP/1.0");
3424
3425 curproxy->check_req = (char *)malloc(reqlen);
3426 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003427 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003429 }
3430 else if (!strcmp(args[1], "ssl-hello-chk")) {
3431 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003432 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003434
Willy Tarreaua534fea2008-08-03 12:19:50 +02003435 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003436 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003437 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003438 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 }
Willy Tarreau23677902007-05-08 23:50:35 +02003440 else if (!strcmp(args[1], "smtpchk")) {
3441 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003442 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003443 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003444 curproxy->options2 &= ~PR_O2_CHK_ANY;
3445 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003446
3447 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3448 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3449 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3450 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3451 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3452 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3453 curproxy->check_req = (char *)malloc(reqlen);
3454 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3455 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3456 } else {
3457 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3458 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3459 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3460 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3461 }
3462 }
3463 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003464 else if (!strcmp(args[1], "pgsql-check")) {
3465 /* use PostgreSQL request to check servers' health */
3466 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3467 err_code |= ERR_WARN;
3468
3469 free(curproxy->check_req);
3470 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003471 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003472 curproxy->options2 |= PR_O2_PGSQL_CHK;
3473
3474 if (*(args[2])) {
3475 int cur_arg = 2;
3476
3477 while (*(args[cur_arg])) {
3478 if (strcmp(args[cur_arg], "user") == 0) {
3479 char * packet;
3480 uint32_t packet_len;
3481 uint32_t pv;
3482
3483 /* suboption header - needs additional argument for it */
3484 if (*(args[cur_arg+1]) == 0) {
3485 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3486 file, linenum, args[0], args[1], args[cur_arg]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490
3491 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3492 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3493 pv = htonl(0x30000); /* protocol version 3.0 */
3494
3495 packet = (char*) calloc(1, packet_len);
3496
3497 memcpy(packet + 4, &pv, 4);
3498
3499 /* copy "user" */
3500 memcpy(packet + 8, "user", 4);
3501
3502 /* copy username */
3503 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3504
3505 free(curproxy->check_req);
3506 curproxy->check_req = packet;
3507 curproxy->check_len = packet_len;
3508
3509 packet_len = htonl(packet_len);
3510 memcpy(packet, &packet_len, 4);
3511 cur_arg += 2;
3512 } else {
3513 /* unknown suboption - catchall */
3514 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3515 file, linenum, args[0], args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 } /* end while loop */
3520 }
3521 }
3522
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003523 else if (!strcmp(args[1], "redis-check")) {
3524 /* use REDIS PING request to check servers' health */
3525 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3526 err_code |= ERR_WARN;
3527
3528 free(curproxy->check_req);
3529 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003530 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003531 curproxy->options2 |= PR_O2_REDIS_CHK;
3532
3533 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3534 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3535 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3536 }
3537
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003538 else if (!strcmp(args[1], "mysql-check")) {
3539 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003540 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3541 err_code |= ERR_WARN;
3542
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003543 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003544 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003545 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003546 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003547
3548 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3549 * const char mysql40_client_auth_pkt[] = {
3550 * "\x0e\x00\x00" // packet length
3551 * "\x01" // packet number
3552 * "\x00\x00" // client capabilities
3553 * "\x00\x00\x01" // max packet
3554 * "haproxy\x00" // username (null terminated string)
3555 * "\x00" // filler (always 0x00)
3556 * "\x01\x00\x00" // packet length
3557 * "\x00" // packet number
3558 * "\x01" // COM_QUIT command
3559 * };
3560 */
3561
3562 if (*(args[2])) {
3563 int cur_arg = 2;
3564
3565 while (*(args[cur_arg])) {
3566 if (strcmp(args[cur_arg], "user") == 0) {
3567 char *mysqluser;
3568 int packetlen, reqlen, userlen;
3569
3570 /* suboption header - needs additional argument for it */
3571 if (*(args[cur_arg+1]) == 0) {
3572 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3573 file, linenum, args[0], args[1], args[cur_arg]);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
3577 mysqluser = args[cur_arg + 1];
3578 userlen = strlen(mysqluser);
3579 packetlen = userlen + 7;
3580 reqlen = packetlen + 9;
3581
3582 free(curproxy->check_req);
3583 curproxy->check_req = (char *)calloc(1, reqlen);
3584 curproxy->check_len = reqlen;
3585
3586 snprintf(curproxy->check_req, 4, "%c%c%c",
3587 ((unsigned char) packetlen & 0xff),
3588 ((unsigned char) (packetlen >> 8) & 0xff),
3589 ((unsigned char) (packetlen >> 16) & 0xff));
3590
3591 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003592 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003593 curproxy->check_req[8] = 1;
3594 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3595 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3596 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3597 cur_arg += 2;
3598 } else {
3599 /* unknown suboption - catchall */
3600 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3601 file, linenum, args[0], args[1]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605 } /* end while loop */
3606 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003607 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003608 else if (!strcmp(args[1], "ldap-check")) {
3609 /* use LDAP request to check servers' health */
3610 free(curproxy->check_req);
3611 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003612 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003613 curproxy->options2 |= PR_O2_LDAP_CHK;
3614
3615 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3616 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3617 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3618 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003619 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003620 int cur_arg;
3621
3622 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3623 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003624 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003625
Willy Tarreau87cf5142011-08-19 22:57:24 +02003626 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003627
3628 free(curproxy->fwdfor_hdr_name);
3629 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3630 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3631
3632 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3633 cur_arg = 2;
3634 while (*(args[cur_arg])) {
3635 if (!strcmp(args[cur_arg], "except")) {
3636 /* suboption except - needs additional argument for it */
3637 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3638 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3639 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003642 }
3643 /* flush useless bits */
3644 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003645 cur_arg += 2;
3646 } else if (!strcmp(args[cur_arg], "header")) {
3647 /* suboption header - needs additional argument for it */
3648 if (*(args[cur_arg+1]) == 0) {
3649 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3650 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003653 }
3654 free(curproxy->fwdfor_hdr_name);
3655 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3656 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3657 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003658 } else if (!strcmp(args[cur_arg], "if-none")) {
3659 curproxy->options &= ~PR_O_FF_ALWAYS;
3660 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003661 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003662 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003663 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003664 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003667 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003668 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003669 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003670 else if (!strcmp(args[1], "originalto")) {
3671 int cur_arg;
3672
3673 /* insert x-original-to field, but not for the IP address listed as an except.
3674 * set default options (ie: bitfield, header name, etc)
3675 */
3676
3677 curproxy->options |= PR_O_ORGTO;
3678
3679 free(curproxy->orgto_hdr_name);
3680 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3681 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3682
Willy Tarreau87cf5142011-08-19 22:57:24 +02003683 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003684 cur_arg = 2;
3685 while (*(args[cur_arg])) {
3686 if (!strcmp(args[cur_arg], "except")) {
3687 /* suboption except - needs additional argument for it */
3688 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3689 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3690 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003693 }
3694 /* flush useless bits */
3695 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3696 cur_arg += 2;
3697 } else if (!strcmp(args[cur_arg], "header")) {
3698 /* suboption header - needs additional argument for it */
3699 if (*(args[cur_arg+1]) == 0) {
3700 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3701 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003704 }
3705 free(curproxy->orgto_hdr_name);
3706 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3707 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3708 cur_arg += 2;
3709 } else {
3710 /* unknown suboption - catchall */
3711 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3712 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003715 }
3716 } /* end while loop */
3717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 else {
3719 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 }
Willy Tarreau93893792009-07-23 13:19:11 +02003723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003725 else if (!strcmp(args[0], "default_backend")) {
3726 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728
3729 if (*(args[1]) == 0) {
3730 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003733 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003734 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003735 curproxy->defbe.name = strdup(args[1]);
3736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003738 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003740
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003741 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3742 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 /* enable reconnections to dispatch */
3745 curproxy->options |= PR_O_REDISP;
3746 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003747 else if (!strcmp(args[0], "http-check")) {
3748 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003750
3751 if (strcmp(args[1], "disable-on-404") == 0) {
3752 /* enable a graceful server shutdown on an HTTP 404 response */
3753 curproxy->options |= PR_O_DISABLE404;
3754 }
Willy Tarreauef781042010-01-27 11:53:01 +01003755 else if (strcmp(args[1], "send-state") == 0) {
3756 /* enable emission of the apparent state of a server in HTTP checks */
3757 curproxy->options2 |= PR_O2_CHK_SNDST;
3758 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003759 else if (strcmp(args[1], "expect") == 0) {
3760 const char *ptr_arg;
3761 int cur_arg;
3762
3763 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3764 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768
3769 cur_arg = 2;
3770 /* consider exclamation marks, sole or at the beginning of a word */
3771 while (*(ptr_arg = args[cur_arg])) {
3772 while (*ptr_arg == '!') {
3773 curproxy->options2 ^= PR_O2_EXP_INV;
3774 ptr_arg++;
3775 }
3776 if (*ptr_arg)
3777 break;
3778 cur_arg++;
3779 }
3780 /* now ptr_arg points to the beginning of a word past any possible
3781 * exclamation mark, and cur_arg is the argument which holds this word.
3782 */
3783 if (strcmp(ptr_arg, "status") == 0) {
3784 if (!*(args[cur_arg + 1])) {
3785 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3786 file, linenum, args[0], args[1], ptr_arg);
3787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
3789 }
3790 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003791 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003792 curproxy->expect_str = strdup(args[cur_arg + 1]);
3793 }
3794 else if (strcmp(ptr_arg, "string") == 0) {
3795 if (!*(args[cur_arg + 1])) {
3796 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3797 file, linenum, args[0], args[1], ptr_arg);
3798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
3800 }
3801 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003802 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003803 curproxy->expect_str = strdup(args[cur_arg + 1]);
3804 }
3805 else if (strcmp(ptr_arg, "rstatus") == 0) {
3806 if (!*(args[cur_arg + 1])) {
3807 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3808 file, linenum, args[0], args[1], ptr_arg);
3809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
3811 }
3812 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003813 free(curproxy->expect_str);
3814 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3815 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003816 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3817 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3818 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3819 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
3823 }
3824 else if (strcmp(ptr_arg, "rstring") == 0) {
3825 if (!*(args[cur_arg + 1])) {
3826 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3827 file, linenum, args[0], args[1], ptr_arg);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003832 free(curproxy->expect_str);
3833 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3834 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003835 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3836 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3837 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3838 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 }
3843 else {
3844 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3845 file, linenum, args[0], args[1], ptr_arg);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003850 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003851 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 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003854 }
3855 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003856 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003857 if (curproxy == &defproxy) {
3858 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003861 }
3862
Willy Tarreaub80c2302007-11-30 20:51:32 +01003863 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003865
3866 if (strcmp(args[1], "fail") == 0) {
3867 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003868 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003869 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3870 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003873 }
3874
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003875 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3876 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3877 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003880 }
3881 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3882 }
3883 else {
3884 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003887 }
3888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889#ifdef TPROXY
3890 else if (!strcmp(args[0], "transparent")) {
3891 /* enable transparent proxy connections */
3892 curproxy->options |= PR_O_TRANSP;
3893 }
3894#endif
3895 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003896 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003898
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 if (*(args[1]) == 0) {
3900 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 }
3904 curproxy->maxconn = atol(args[1]);
3905 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003906 else if (!strcmp(args[0], "backlog")) { /* backlog */
3907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003908 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003909
3910 if (*(args[1]) == 0) {
3911 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003914 }
3915 curproxy->backlog = atol(args[1]);
3916 }
Willy Tarreau86034312006-12-29 00:10:33 +01003917 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003920
Willy Tarreau86034312006-12-29 00:10:33 +01003921 if (*(args[1]) == 0) {
3922 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003925 }
3926 curproxy->fullconn = atol(args[1]);
3927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3929 if (*(args[1]) == 0) {
3930 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003934 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3935 if (err) {
3936 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3937 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003940 }
3941 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
3943 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003944 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 if (curproxy == &defproxy) {
3946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003950 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 if (strchr(args[1], ':') == NULL) {
3954 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003958 sk = str2sa(args[1]);
3959 if (!sk) {
3960 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003965 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966 }
3967 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003970
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003971 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3972 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003977 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3978 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3979 err_code |= ERR_WARN;
3980
3981 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3982 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3983 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3984 }
3985 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3986 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3987 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3988 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003989 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3990 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3991 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3992 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003993 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003994 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003999 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004001 char *rport, *raddr;
4002 short realport = 0;
4003 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004005 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004010 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012
4013 if (!*args[2]) {
4014 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004019
4020 err = invalid_char(args[1]);
4021 if (err) {
4022 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4023 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004026 }
4027
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004028 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004029 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004030
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004031 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4032 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4033 err_code |= ERR_ALERT | ERR_ABORT;
4034 goto out;
4035 }
4036
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004037 /* the servers are linked backwards first */
4038 newsrv->next = curproxy->srv;
4039 curproxy->srv = newsrv;
4040 newsrv->proxy = curproxy;
4041 newsrv->conf.file = file;
4042 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043
Simon Hormanaf514952011-06-21 14:34:57 +09004044 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 LIST_INIT(&newsrv->pendconns);
4046 do_check = 0;
4047 newsrv->state = SRV_RUNNING; /* early server setup */
4048 newsrv->last_change = now.tv_sec;
4049 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004051 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004052 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 * - IP: => port=+0, relative
4054 * - IP:N => port=N, absolute
4055 * - IP:+N => port=+N, relative
4056 * - IP:-N => port=-N, relative
4057 */
4058 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004059 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004060 if (rport) {
4061 *rport++ = 0;
4062 realport = atol(rport);
4063 if (!isdigit((unsigned char)*rport))
4064 newsrv->state |= SRV_MAPPORTS;
4065 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004067
Willy Tarreaufab5a432011-03-04 15:31:53 +01004068 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004069 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004070 if (!sk) {
4071 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004076 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004077 newsrv->sock = &sock_raw;
4078 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004079
4080 if (!sk) {
4081 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4082 file, linenum, newsrv->addr.ss_family, args[2]);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004086 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004087
4088 newsrv->check_port = curproxy->defsrv.check_port;
4089 newsrv->inter = curproxy->defsrv.inter;
4090 newsrv->fastinter = curproxy->defsrv.fastinter;
4091 newsrv->downinter = curproxy->defsrv.downinter;
4092 newsrv->rise = curproxy->defsrv.rise;
4093 newsrv->fall = curproxy->defsrv.fall;
4094 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4095 newsrv->minconn = curproxy->defsrv.minconn;
4096 newsrv->maxconn = curproxy->defsrv.maxconn;
4097 newsrv->slowstart = curproxy->defsrv.slowstart;
4098 newsrv->onerror = curproxy->defsrv.onerror;
4099 newsrv->consecutive_errors_limit
4100 = curproxy->defsrv.consecutive_errors_limit;
4101 newsrv->uweight = newsrv->iweight
4102 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004104 newsrv->curfd = -1; /* no health-check in progress */
4105 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004107 cur_arg = 3;
4108 } else {
4109 newsrv = &curproxy->defsrv;
4110 cur_arg = 1;
4111 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004112
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004115 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004116
4117 if (!*args[cur_arg + 1]) {
4118 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4119 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004122 }
4123
4124 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004125 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004126
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004127 if (newsrv->puid <= 0) {
4128 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004129 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004132 }
4133
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004134 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4135 if (node) {
4136 struct server *target = container_of(node, struct server, conf.id);
4137 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4138 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
4141 }
4142 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004143 cur_arg += 2;
4144 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004145 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 newsrv->cookie = strdup(args[cur_arg + 1]);
4147 newsrv->cklen = strlen(args[cur_arg + 1]);
4148 cur_arg += 2;
4149 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004151 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4152 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4153 cur_arg += 2;
4154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004156 if (!*args[cur_arg + 1]) {
4157 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4158 file, linenum, args[cur_arg]);
4159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
4161 }
4162
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004164 if (newsrv->rise <= 0) {
4165 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4166 file, linenum, args[cur_arg]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170
Willy Tarreau96839092010-03-29 10:02:24 +02004171 if (newsrv->health)
4172 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 cur_arg += 2;
4174 }
4175 else if (!strcmp(args[cur_arg], "fall")) {
4176 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004177
4178 if (!*args[cur_arg + 1]) {
4179 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4180 file, linenum, args[cur_arg]);
4181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
4183 }
4184
4185 if (newsrv->fall <= 0) {
4186 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4187 file, linenum, args[cur_arg]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 cur_arg += 2;
4193 }
4194 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004195 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4196 if (err) {
4197 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4198 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004201 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004202 if (val <= 0) {
4203 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4204 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004207 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004208 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 cur_arg += 2;
4210 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004211 else if (!strcmp(args[cur_arg], "fastinter")) {
4212 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4213 if (err) {
4214 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4215 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004218 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004219 if (val <= 0) {
4220 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4221 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004224 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004225 newsrv->fastinter = val;
4226 cur_arg += 2;
4227 }
4228 else if (!strcmp(args[cur_arg], "downinter")) {
4229 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4230 if (err) {
4231 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4232 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004235 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004236 if (val <= 0) {
4237 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4238 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004241 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004242 newsrv->downinter = val;
4243 cur_arg += 2;
4244 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004245 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004246 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004247 if (!sk) {
4248 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004253 cur_arg += 2;
4254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 else if (!strcmp(args[cur_arg], "port")) {
4256 newsrv->check_port = atol(args[cur_arg + 1]);
4257 cur_arg += 2;
4258 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004259 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 newsrv->state |= SRV_BACKUP;
4261 cur_arg ++;
4262 }
Simon Hormanfa461682011-06-25 09:39:49 +09004263 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4264 newsrv->state |= SRV_NON_STICK;
4265 cur_arg ++;
4266 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004267 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4268 newsrv->state |= SRV_SEND_PROXY;
4269 cur_arg ++;
4270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 else if (!strcmp(args[cur_arg], "weight")) {
4272 int w;
4273 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004274 if (w < 0 || w > 256) {
4275 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004280 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 cur_arg += 2;
4282 }
4283 else if (!strcmp(args[cur_arg], "minconn")) {
4284 newsrv->minconn = atol(args[cur_arg + 1]);
4285 cur_arg += 2;
4286 }
4287 else if (!strcmp(args[cur_arg], "maxconn")) {
4288 newsrv->maxconn = atol(args[cur_arg + 1]);
4289 cur_arg += 2;
4290 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004291 else if (!strcmp(args[cur_arg], "maxqueue")) {
4292 newsrv->maxqueue = atol(args[cur_arg + 1]);
4293 cur_arg += 2;
4294 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004295 else if (!strcmp(args[cur_arg], "slowstart")) {
4296 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004297 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004298 if (err) {
4299 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4300 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004303 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004304 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004305 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4306 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004309 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004310 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004311 cur_arg += 2;
4312 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004313 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004314
4315 if (!*args[cur_arg + 1]) {
4316 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004320 }
4321
4322 newsrv->trackit = strdup(args[cur_arg + 1]);
4323
4324 cur_arg += 2;
4325 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004326 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 global.maxsock++;
4328 do_check = 1;
4329 cur_arg += 1;
4330 }
Willy Tarreau96839092010-03-29 10:02:24 +02004331 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4332 newsrv->state |= SRV_MAINTAIN;
4333 newsrv->state &= ~SRV_RUNNING;
4334 newsrv->health = 0;
4335 cur_arg += 1;
4336 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004337 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004338 if (!strcmp(args[cur_arg + 1], "none"))
4339 newsrv->observe = HANA_OBS_NONE;
4340 else if (!strcmp(args[cur_arg + 1], "layer4"))
4341 newsrv->observe = HANA_OBS_LAYER4;
4342 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4343 if (curproxy->mode != PR_MODE_HTTP) {
4344 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4345 file, linenum, args[cur_arg + 1]);
4346 err_code |= ERR_ALERT;
4347 }
4348 newsrv->observe = HANA_OBS_LAYER7;
4349 }
4350 else {
4351 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004352 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004353 file, linenum, args[cur_arg], args[cur_arg + 1]);
4354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
4356 }
4357
4358 cur_arg += 2;
4359 }
4360 else if (!strcmp(args[cur_arg], "on-error")) {
4361 if (!strcmp(args[cur_arg + 1], "fastinter"))
4362 newsrv->onerror = HANA_ONERR_FASTINTER;
4363 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4364 newsrv->onerror = HANA_ONERR_FAILCHK;
4365 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4366 newsrv->onerror = HANA_ONERR_SUDDTH;
4367 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4368 newsrv->onerror = HANA_ONERR_MARKDWN;
4369 else {
4370 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004371 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004372 file, linenum, args[cur_arg], args[cur_arg + 1]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376
4377 cur_arg += 2;
4378 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004379 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4380 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4381 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4382 else {
4383 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4384 file, linenum, args[cur_arg], args[cur_arg + 1]);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388
4389 cur_arg += 2;
4390 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004391 else if (!strcmp(args[cur_arg], "error-limit")) {
4392 if (!*args[cur_arg + 1]) {
4393 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4394 file, linenum, args[cur_arg]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398
4399 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4400
4401 if (newsrv->consecutive_errors_limit <= 0) {
4402 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4403 file, linenum, args[cur_arg]);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004407 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004408 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004409 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004410 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004411 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004412
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004414#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004415 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004416 file, linenum, "source", "usesrc");
4417#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004418 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004420#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 }
4424 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004425 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4426 if (!sk) {
4427 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 }
4431 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004432
4433 if (port_low != port_high) {
4434 int i;
4435 if (port_low <= 0 || port_low > 65535 ||
4436 port_high <= 0 || port_high > 65535 ||
4437 port_low > port_high) {
4438 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4439 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004442 }
4443 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4444 for (i = 0; i < newsrv->sport_range->size; i++)
4445 newsrv->sport_range->ports[i] = port_low + i;
4446 }
4447
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004449 while (*(args[cur_arg])) {
4450 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004451#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4452#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004453 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4454 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4455 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004458 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004459#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004460 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004461 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004462 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 }
4466 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004467 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004468 newsrv->state |= SRV_TPROXY_CLI;
4469 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004470 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004471 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004472 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4473 char *name, *end;
4474
4475 name = args[cur_arg+1] + 7;
4476 while (isspace(*name))
4477 name++;
4478
4479 end = name;
4480 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4481 end++;
4482
4483 newsrv->state &= ~SRV_TPROXY_MASK;
4484 newsrv->state |= SRV_TPROXY_DYN;
4485 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4486 newsrv->bind_hdr_len = end - name;
4487 memcpy(newsrv->bind_hdr_name, name, end - name);
4488 newsrv->bind_hdr_name[end-name] = '\0';
4489 newsrv->bind_hdr_occ = -1;
4490
4491 /* now look for an occurrence number */
4492 while (isspace(*end))
4493 end++;
4494 if (*end == ',') {
4495 end++;
4496 name = end;
4497 if (*end == '-')
4498 end++;
4499 while (isdigit(*end))
4500 end++;
4501 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4502 }
4503
4504 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4505 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4506 " occurrences values smaller than %d.\n",
4507 file, linenum, MAX_HDR_HISTORY);
4508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
4510 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004511 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004512 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004513 if (!sk) {
4514 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
4517 }
4518 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 }
4521 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004522#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004524#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 cur_arg += 2;
4526 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004527#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004528 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004529 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004532#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4533 } /* "usesrc" */
4534
4535 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4536#ifdef SO_BINDTODEVICE
4537 if (!*args[cur_arg + 1]) {
4538 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4539 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004542 }
4543 if (newsrv->iface_name)
4544 free(newsrv->iface_name);
4545
4546 newsrv->iface_name = strdup(args[cur_arg + 1]);
4547 newsrv->iface_len = strlen(newsrv->iface_name);
4548 global.last_checks |= LSTCHK_NETADM;
4549#else
4550 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4551 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004554#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004555 cur_arg += 2;
4556 continue;
4557 }
4558 /* this keyword in not an option of "source" */
4559 break;
4560 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004562 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004563 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4564 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004569 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004570 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 +01004571 file, linenum, newsrv->id);
4572 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004573 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 +01004574 file, linenum);
4575
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
4579 }
4580
4581 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004582 if (newsrv->trackit) {
4583 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4584 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004587 }
4588
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004589 /* try to get the port from check_addr if check_port not set */
4590 if (!newsrv->check_port)
4591 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004592
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4594 newsrv->check_port = realport; /* by default */
4595 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004596 /* not yet valid, because no port was set on
4597 * the server either. We'll check if we have
4598 * a known port on the first listener.
4599 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004600 struct listener *l = curproxy->listen;
4601 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4602 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004603 }
4604 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4606 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004610
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004611 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004612 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004613 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4614 err_code |= ERR_ALERT | ERR_ABORT;
4615 goto out;
4616 }
4617
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004618 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 newsrv->state |= SRV_CHECKED;
4620 }
4621
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 if (!defsrv) {
4623 if (newsrv->state & SRV_BACKUP)
4624 curproxy->srv_bck++;
4625 else
4626 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004627
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004628 newsrv->prev_state = newsrv->state;
4629 }
William Lallemanda73203e2012-03-12 12:48:57 +01004630 }
4631
4632 else if (strcmp(args[0], "unique-id-format") == 0) {
4633 if (!*(args[1])) {
4634 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
4637 }
4638 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004639 }
William Lallemanda73203e2012-03-12 12:48:57 +01004640
4641 else if (strcmp(args[0], "unique-id-header") == 0) {
4642 if (!*(args[1])) {
4643 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4644 err_code |= ERR_ALERT | ERR_FATAL;
4645 goto out;
4646 }
4647 free(curproxy->header_unique_id);
4648 curproxy->header_unique_id = strdup(args[1]);
4649 }
4650
William Lallemand723b73a2012-02-08 16:37:49 +01004651 else if (strcmp(args[0], "log-format") == 0) {
4652 if (!*(args[1])) {
4653 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
4656 }
William Lallemand1d705562012-03-12 12:46:41 +01004657 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 }
William Lallemand723b73a2012-02-08 16:37:49 +01004659
William Lallemand0f99e342011-10-12 17:50:54 +02004660 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4661 /* delete previous herited or defined syslog servers */
4662 struct logsrv *back;
4663
4664 if (*(args[1]) != 0) {
4665 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669
William Lallemand723b73a2012-02-08 16:37:49 +01004670 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4671 LIST_DEL(&tmplogsrv->list);
4672 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004673 }
4674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004676 struct logsrv *logsrv;
4677
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004679 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004680 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004681 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004682 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004683 LIST_INIT(&node->list);
4684 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
4687 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004688
4689 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690
William Lallemand0f99e342011-10-12 17:50:54 +02004691 logsrv->facility = get_log_facility(args[2]);
4692 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 }
4698
William Lallemand0f99e342011-10-12 17:50:54 +02004699 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004701 logsrv->level = get_log_level(args[3]);
4702 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
4706
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
4708 }
4709
William Lallemand0f99e342011-10-12 17:50:54 +02004710 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004711 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004712 logsrv->minlvl = get_log_level(args[4]);
4713 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004714 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004718 }
4719 }
4720
Robert Tsai81ae1952007-12-05 10:47:29 +01004721 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004722 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004723 if (!sk) {
4724 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004725 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
4728 }
William Lallemand0f99e342011-10-12 17:50:54 +02004729 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004730 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004731 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004732 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004733 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
4736 }
William Lallemand0f99e342011-10-12 17:50:54 +02004737 logsrv->addr = *sk;
4738 if (!get_host_port(&logsrv->addr))
4739 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
William Lallemand0f99e342011-10-12 17:50:54 +02004741
4742 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else {
4745 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4746 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
4750 }
4751 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004752 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004753 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004754
Willy Tarreau977b8e42006-12-29 14:19:17 +01004755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004757
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004759 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4760 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004764
4765 /* we must first clear any optional default setting */
4766 curproxy->options &= ~PR_O_TPXY_MASK;
4767 free(curproxy->iface_name);
4768 curproxy->iface_name = NULL;
4769 curproxy->iface_len = 0;
4770
Willy Tarreaud5191e72010-02-09 20:50:45 +01004771 sk = str2sa(args[1]);
4772 if (!sk) {
4773 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
4777 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004779
4780 cur_arg = 2;
4781 while (*(args[cur_arg])) {
4782 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004783#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4784#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004785 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4786 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4787 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004790 }
4791#endif
4792 if (!*args[cur_arg + 1]) {
4793 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4794 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004797 }
4798
4799 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004800 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 curproxy->options |= PR_O_TPXY_CLI;
4802 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004803 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004804 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004805 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4806 char *name, *end;
4807
4808 name = args[cur_arg+1] + 7;
4809 while (isspace(*name))
4810 name++;
4811
4812 end = name;
4813 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4814 end++;
4815
4816 curproxy->options &= ~PR_O_TPXY_MASK;
4817 curproxy->options |= PR_O_TPXY_DYN;
4818 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4819 curproxy->bind_hdr_len = end - name;
4820 memcpy(curproxy->bind_hdr_name, name, end - name);
4821 curproxy->bind_hdr_name[end-name] = '\0';
4822 curproxy->bind_hdr_occ = -1;
4823
4824 /* now look for an occurrence number */
4825 while (isspace(*end))
4826 end++;
4827 if (*end == ',') {
4828 end++;
4829 name = end;
4830 if (*end == '-')
4831 end++;
4832 while (isdigit(*end))
4833 end++;
4834 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4835 }
4836
4837 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4838 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4839 " occurrences values smaller than %d.\n",
4840 file, linenum, MAX_HDR_HISTORY);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004844 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004845 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004846 if (!sk) {
4847 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004852 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 }
4854 global.last_checks |= LSTCHK_NETADM;
4855#if !defined(CONFIG_HAP_LINUX_TPROXY)
4856 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004857#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858#else /* no TPROXY support */
4859 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004860 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004863#endif
4864 cur_arg += 2;
4865 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004866 }
4867
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4869#ifdef SO_BINDTODEVICE
4870 if (!*args[cur_arg + 1]) {
4871 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4872 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 }
4876 if (curproxy->iface_name)
4877 free(curproxy->iface_name);
4878
4879 curproxy->iface_name = strdup(args[cur_arg + 1]);
4880 curproxy->iface_len = strlen(curproxy->iface_name);
4881 global.last_checks |= LSTCHK_NETADM;
4882#else
4883 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4884 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004887#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004888 cur_arg += 2;
4889 continue;
4890 }
4891 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4892 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004897 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4898 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4899 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910
4911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004912 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004913 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004919 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004926 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004927 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004933 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004940 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004945 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004947 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004951 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004952 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004954 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004958 }
4959 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973
4974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005003 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005004 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005008 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005016 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005017
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 if (curproxy == &defproxy) {
5019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005023 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 if (*(args[1]) == 0) {
5027 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005031
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005032 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005033 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5034 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5035 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
5039 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5040 }
5041 else if (*args[2]) {
5042 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5043 file, linenum, args[0], args[2]);
5044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
5046 }
5047
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005048 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005049 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005050 wl->s = strdup(args[1]);
5051 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005052 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005061
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005063 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005064 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
5068 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005070 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005071 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 }
5075 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005077 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005078 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
5082 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 }
5089
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005091 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005092 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005093 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
5096 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005098 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005099 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005100 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005105 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005106 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005111 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005112
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 if (curproxy == &defproxy) {
5114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 if (*(args[1]) == 0) {
5122 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005127 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005128 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5129 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5130 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
5133 }
5134 err_code |= warnif_cond_requires_req(cond, file, linenum);
5135 }
5136 else if (*args[2]) {
5137 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5138 file, linenum, args[0], args[2]);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
5142
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005143 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005144 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005145 wl->s = strdup(args[1]);
5146 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "errorloc") ||
5149 !strcmp(args[0], "errorloc302") ||
5150 !strcmp(args[0], "errorloc303")) { /* error location */
5151 int errnum, errlen;
5152 char *err;
5153
Willy Tarreau977b8e42006-12-29 14:19:17 +01005154 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005156
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005158 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162
5163 errnum = atol(args[1]);
5164 if (!strcmp(args[0], "errorloc303")) {
5165 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5166 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5167 } else {
5168 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5169 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5170 }
5171
Willy Tarreau0f772532006-12-23 20:51:41 +01005172 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5173 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005174 chunk_destroy(&curproxy->errmsg[rc]);
5175 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005176 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005179
5180 if (rc >= HTTP_ERR_SIZE) {
5181 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5182 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 free(err);
5184 }
5185 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005186 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5187 int errnum, errlen, fd;
5188 char *err;
5189 struct stat stat;
5190
5191 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005193
5194 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005195 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005198 }
5199
5200 fd = open(args[2], O_RDONLY);
5201 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5202 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5203 file, linenum, args[2], args[1]);
5204 if (fd >= 0)
5205 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005208 }
5209
Willy Tarreau27a674e2009-08-17 07:23:33 +02005210 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005211 errlen = stat.st_size;
5212 } else {
5213 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005214 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005216 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217 }
5218
5219 err = malloc(errlen); /* malloc() must succeed during parsing */
5220 errnum = read(fd, err, errlen);
5221 if (errnum != errlen) {
5222 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5223 file, linenum, args[2], args[1]);
5224 close(fd);
5225 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005228 }
5229 close(fd);
5230
5231 errnum = atol(args[1]);
5232 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5233 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005234 chunk_destroy(&curproxy->errmsg[rc]);
5235 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005236 break;
5237 }
5238 }
5239
5240 if (rc >= HTTP_ERR_SIZE) {
5241 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5242 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005244 free(err);
5245 }
5246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005248 struct cfg_kw_list *kwl;
5249 int index;
5250
5251 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5252 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5253 if (kwl->kw[index].section != CFG_LISTEN)
5254 continue;
5255 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5256 /* prepare error message just in case */
5257 snprintf(trash, sizeof(trash),
5258 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005259 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005260 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005261 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005264 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005265 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005266 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_WARN;
5268 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005269 }
Willy Tarreau93893792009-07-23 13:19:11 +02005270 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005271 }
5272 }
5273 }
5274
Willy Tarreau6daf3432008-01-22 16:44:08 +01005275 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
Willy Tarreau93893792009-07-23 13:19:11 +02005279 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005280 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282}
5283
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005284int
5285cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5286{
5287
5288 int err_code = 0;
5289 const char *err;
5290
5291 if (!strcmp(args[0], "userlist")) { /* new userlist */
5292 struct userlist *newul;
5293
5294 if (!*args[1]) {
5295 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5296 file, linenum, args[0]);
5297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
5299 }
5300
5301 err = invalid_char(args[1]);
5302 if (err) {
5303 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5304 file, linenum, *err, args[0], args[1]);
5305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308
5309 for (newul = userlist; newul; newul = newul->next)
5310 if (!strcmp(newul->name, args[1])) {
5311 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5312 file, linenum, args[1]);
5313 err_code |= ERR_WARN;
5314 goto out;
5315 }
5316
5317 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5318 if (!newul) {
5319 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5320 err_code |= ERR_ALERT | ERR_ABORT;
5321 goto out;
5322 }
5323
5324 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5325 newul->name = strdup(args[1]);
5326
5327 if (!newul->groupusers | !newul->name) {
5328 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5329 err_code |= ERR_ALERT | ERR_ABORT;
5330 goto out;
5331 }
5332
5333 newul->next = userlist;
5334 userlist = newul;
5335
5336 } else if (!strcmp(args[0], "group")) { /* new group */
5337 int cur_arg, i;
5338 const char *err;
5339
5340 if (!*args[1]) {
5341 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5342 file, linenum, args[0]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346
5347 err = invalid_char(args[1]);
5348 if (err) {
5349 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5350 file, linenum, *err, args[0], args[1]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354
5355 for(i = 0; i < userlist->grpcnt; i++)
5356 if (!strcmp(userlist->groups[i], args[1])) {
5357 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5358 file, linenum, args[1], userlist->name);
5359 err_code |= ERR_ALERT;
5360 goto out;
5361 }
5362
5363 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5364 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5365 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369
5370 cur_arg = 2;
5371
5372 while (*args[cur_arg]) {
5373 if (!strcmp(args[cur_arg], "users")) {
5374 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5375 cur_arg += 2;
5376 continue;
5377 } else {
5378 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5379 file, linenum, args[0]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383 }
5384
5385 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5386 } else if (!strcmp(args[0], "user")) { /* new user */
5387 struct auth_users *newuser;
5388 int cur_arg;
5389
5390 if (!*args[1]) {
5391 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5392 file, linenum, args[0]);
5393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
5396
5397 for (newuser = userlist->users; newuser; newuser = newuser->next)
5398 if (!strcmp(newuser->user, args[1])) {
5399 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5400 file, linenum, args[1], userlist->name);
5401 err_code |= ERR_ALERT;
5402 goto out;
5403 }
5404
5405 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5406 if (!newuser) {
5407 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5408 err_code |= ERR_ALERT | ERR_ABORT;
5409 goto out;
5410 }
5411
5412 newuser->user = strdup(args[1]);
5413
5414 newuser->next = userlist->users;
5415 userlist->users = newuser;
5416
5417 cur_arg = 2;
5418
5419 while (*args[cur_arg]) {
5420 if (!strcmp(args[cur_arg], "password")) {
5421#ifndef CONFIG_HAP_CRYPT
5422 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5423 file, linenum);
5424 err_code |= ERR_ALERT;
5425#endif
5426 newuser->pass = strdup(args[cur_arg + 1]);
5427 cur_arg += 2;
5428 continue;
5429 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5430 newuser->pass = strdup(args[cur_arg + 1]);
5431 newuser->flags |= AU_O_INSECURE;
5432 cur_arg += 2;
5433 continue;
5434 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005435 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005436 cur_arg += 2;
5437 continue;
5438 } else {
5439 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5440 file, linenum, args[0]);
5441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
5443 }
5444 }
5445 } else {
5446 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 }
5449
5450out:
5451 return err_code;
5452}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453
5454/*
5455 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005456 * Returns the error code, 0 if OK, or any combination of :
5457 * - ERR_ABORT: must abort ASAP
5458 * - ERR_FATAL: we can continue parsing but not start the service
5459 * - ERR_WARN: a warning has been emitted
5460 * - ERR_ALERT: an alert has been emitted
5461 * Only the two first ones can stop processing, the two others are just
5462 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005464int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005466 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 FILE *f;
5468 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005470 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 if ((f=fopen(file,"r")) == NULL)
5473 return -1;
5474
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005475 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005476 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005477 char *end;
5478 char *args[MAX_LINE_ARGS + 1];
5479 char *line = thisline;
5480
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 linenum++;
5482
5483 end = line + strlen(line);
5484
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005485 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5486 /* Check if we reached the limit and the last char is not \n.
5487 * Watch out for the last line without the terminating '\n'!
5488 */
5489 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005490 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005491 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005492 }
5493
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005495 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 line++;
5497
5498 arg = 0;
5499 args[arg] = line;
5500
5501 while (*line && arg < MAX_LINE_ARGS) {
5502 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5503 * C equivalent value. Other combinations left unchanged (eg: \1).
5504 */
5505 if (*line == '\\') {
5506 int skip = 0;
5507 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5508 *line = line[1];
5509 skip = 1;
5510 }
5511 else if (line[1] == 'r') {
5512 *line = '\r';
5513 skip = 1;
5514 }
5515 else if (line[1] == 'n') {
5516 *line = '\n';
5517 skip = 1;
5518 }
5519 else if (line[1] == 't') {
5520 *line = '\t';
5521 skip = 1;
5522 }
5523 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005524 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 unsigned char hex1, hex2;
5526 hex1 = toupper(line[2]) - '0';
5527 hex2 = toupper(line[3]) - '0';
5528 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5529 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5530 *line = (hex1<<4) + hex2;
5531 skip = 3;
5532 }
5533 else {
5534 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
5537 }
5538 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005539 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 end -= skip;
5541 }
5542 line++;
5543 }
5544 else if (*line == '#' || *line == '\n' || *line == '\r') {
5545 /* end of string, end of loop */
5546 *line = 0;
5547 break;
5548 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005549 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005551 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005552 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 line++;
5554 args[++arg] = line;
5555 }
5556 else {
5557 line++;
5558 }
5559 }
5560
5561 /* empty line */
5562 if (!**args)
5563 continue;
5564
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005565 if (*line) {
5566 /* we had to stop due to too many args.
5567 * Let's terminate the string, print the offending part then cut the
5568 * last arg.
5569 */
5570 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5571 line++;
5572 *line = '\0';
5573
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005574 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005575 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005576 err_code |= ERR_ALERT | ERR_FATAL;
5577 args[arg] = line;
5578 }
5579
Willy Tarreau540abe42007-05-02 20:50:16 +02005580 /* zero out remaining args and ensure that at least one entry
5581 * is zeroed out.
5582 */
5583 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 args[arg] = line;
5585 }
5586
Willy Tarreau3842f002009-06-14 11:39:52 +02005587 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005588 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005589 char *tmp;
5590
Willy Tarreau3842f002009-06-14 11:39:52 +02005591 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005592 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005593 for (arg=0; *args[arg+1]; arg++)
5594 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005595 *tmp = '\0'; // fix the next arg to \0
5596 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005597 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005598 else if (!strcmp(args[0], "default")) {
5599 kwm = KWM_DEF;
5600 for (arg=0; *args[arg+1]; arg++)
5601 args[arg] = args[arg+1]; // shift args after inversion
5602 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005603
William Lallemand0f99e342011-10-12 17:50:54 +02005604 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5605 strcmp(args[0], "log") != 0) {
5606 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005607 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005608 }
5609
Willy Tarreau977b8e42006-12-29 14:19:17 +01005610 if (!strcmp(args[0], "listen") ||
5611 !strcmp(args[0], "frontend") ||
5612 !strcmp(args[0], "backend") ||
5613 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005614 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005616 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005617 cursection = strdup(args[0]);
5618 }
5619 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005621 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005622 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005623 }
5624 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005625 confsect = CFG_USERLIST;
5626 free(cursection);
5627 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005628 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005629 else if (!strcmp(args[0], "peers")) {
5630 confsect = CFG_PEERS;
5631 free(cursection);
5632 cursection = strdup(args[0]);
5633 }
5634
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 /* else it's a section keyword */
5636
5637 switch (confsect) {
5638 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005639 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 break;
5641 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005642 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005644 case CFG_USERLIST:
5645 err_code |= cfg_parse_users(file, linenum, args, kwm);
5646 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005647 case CFG_PEERS:
5648 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5649 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005651 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005654
5655 if (err_code & ERR_ABORT)
5656 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005658 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005659 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005661 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005662}
5663
Willy Tarreaubb925012009-07-23 13:36:36 +02005664/*
5665 * Returns the error code, 0 if OK, or any combination of :
5666 * - ERR_ABORT: must abort ASAP
5667 * - ERR_FATAL: we can continue parsing but not start the service
5668 * - ERR_WARN: a warning has been emitted
5669 * - ERR_ALERT: an alert has been emitted
5670 * Only the two first ones can stop processing, the two others are just
5671 * indicators.
5672 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005673int check_config_validity()
5674{
5675 int cfgerr = 0;
5676 struct proxy *curproxy = NULL;
5677 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005678 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005679 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005680 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681
5682 /*
5683 * Now, check for the integrity of all that we have collected.
5684 */
5685
5686 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005687 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005689 /* first, we will invert the proxy list order */
5690 curproxy = NULL;
5691 while (proxy) {
5692 struct proxy *next;
5693
5694 next = proxy->next;
5695 proxy->next = curproxy;
5696 curproxy = proxy;
5697 if (!next)
5698 break;
5699 proxy = next;
5700 }
5701
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005703 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005704 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005705 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005706 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005707 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005708 unsigned int next_id;
5709
5710 if (!curproxy->uuid) {
5711 /* proxy ID not set, use automatic numbering with first
5712 * spare entry starting with next_pxid.
5713 */
5714 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5715 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5716 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005717 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005718 next_pxid++;
5719
Willy Tarreau55ea7572007-06-17 19:56:27 +02005720
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005722 /* ensure we don't keep listeners uselessly bound */
5723 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 curproxy = curproxy->next;
5725 continue;
5726 }
5727
Willy Tarreauff01a212009-03-15 13:46:16 +01005728 switch (curproxy->mode) {
5729 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005730 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005731 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005732 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5733 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005734 cfgerr++;
5735 }
5736
5737 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005738 Warning("config : servers will be ignored for %s '%s'.\n",
5739 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005740 break;
5741
5742 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005743 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005744 break;
5745
5746 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005747 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005748 break;
5749 }
5750
5751 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005752 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5753 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 cfgerr++;
5755 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005756
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005757 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005758 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005759 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005760 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5761 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005762 cfgerr++;
5763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005765 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005766 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5767 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005768 cfgerr++;
5769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005771 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005772 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5773 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005774 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005775 }
5776 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005777 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005778 /* If no LB algo is set in a backend, and we're not in
5779 * transparent mode, dispatch mode nor proxy mode, we
5780 * want to use balance roundrobin by default.
5781 */
5782 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5783 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005786
Willy Tarreau1620ec32011-08-06 17:05:02 +02005787 if (curproxy->options & PR_O_DISPATCH)
5788 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5789 else if (curproxy->options & PR_O_HTTP_PROXY)
5790 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5791 else if (curproxy->options & PR_O_TRANSP)
5792 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005793
Willy Tarreau1620ec32011-08-06 17:05:02 +02005794 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5795 if (curproxy->options & PR_O_DISABLE404) {
5796 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5797 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5798 err_code |= ERR_WARN;
5799 curproxy->options &= ~PR_O_DISABLE404;
5800 }
5801 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5802 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5803 "send-state", proxy_type_str(curproxy), curproxy->id);
5804 err_code |= ERR_WARN;
5805 curproxy->options &= ~PR_O2_CHK_SNDST;
5806 }
Willy Tarreauef781042010-01-27 11:53:01 +01005807 }
5808
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005809 /* if a default backend was specified, let's find it */
5810 if (curproxy->defbe.name) {
5811 struct proxy *target;
5812
Alex Williams96532db2009-11-01 21:27:13 -05005813 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005814 if (!target) {
5815 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5816 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005817 cfgerr++;
5818 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005819 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5820 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005821 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005822 } else {
5823 free(curproxy->defbe.name);
5824 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005825 /* we force the backend to be present on at least all of
5826 * the frontend's processes.
5827 */
5828 target->bind_proc = curproxy->bind_proc ?
5829 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005830
5831 /* Emit a warning if this proxy also has some servers */
5832 if (curproxy->srv) {
5833 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5834 curproxy->id);
5835 err_code |= ERR_WARN;
5836 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 }
5838 }
5839
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005840 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005841 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5842 /* map jump target for ACT_SETBE in req_rep chain */
5843 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005844 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005845 struct proxy *target;
5846
Willy Tarreaua496b602006-12-17 23:15:24 +01005847 if (exp->action != ACT_SETBE)
5848 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005849
Alex Williams96532db2009-11-01 21:27:13 -05005850 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005851 if (!target) {
5852 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5853 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005854 cfgerr++;
5855 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005856 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5857 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005858 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005859 } else {
5860 free((void *)exp->replace);
5861 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005862 /* we force the backend to be present on at least all of
5863 * the frontend's processes.
5864 */
5865 target->bind_proc = curproxy->bind_proc ?
5866 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005867 }
5868 }
5869 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005870
5871 /* find the target proxy for 'use_backend' rules */
5872 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005873 struct proxy *target;
5874
Alex Williams96532db2009-11-01 21:27:13 -05005875 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005876
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005877 if (!target) {
5878 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5879 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005880 cfgerr++;
5881 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005882 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5883 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005884 cfgerr++;
5885 } else {
5886 free((void *)rule->be.name);
5887 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005888 /* we force the backend to be present on at least all of
5889 * the frontend's processes.
5890 */
5891 target->bind_proc = curproxy->bind_proc ?
5892 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005893 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005894 }
5895
5896 /* find the target proxy for 'use_backend' rules */
5897 list_for_each_entry(srule, &curproxy->server_rules, list) {
5898 struct server *target = findserver(curproxy, srule->srv.name);
5899
5900 if (!target) {
5901 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5902 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5903 cfgerr++;
5904 continue;
5905 }
5906 free((void *)srule->srv.name);
5907 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005908 }
5909
Emeric Brunb982a3d2010-01-04 15:45:53 +01005910 /* find the target table for 'stick' rules */
5911 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5912 struct proxy *target;
5913
Emeric Brun1d33b292010-01-04 15:47:17 +01005914 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5915 if (mrule->flags & STK_IS_STORE)
5916 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5917
Emeric Brunb982a3d2010-01-04 15:45:53 +01005918 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005919 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005920 else
5921 target = curproxy;
5922
5923 if (!target) {
5924 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5925 curproxy->id, mrule->table.name);
5926 cfgerr++;
5927 }
5928 else if (target->table.size == 0) {
5929 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5930 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5931 cfgerr++;
5932 }
Willy Tarreau12785782012-04-27 21:37:17 +02005933 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5934 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005935 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5936 cfgerr++;
5937 }
5938 else {
5939 free((void *)mrule->table.name);
5940 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005941 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005942 }
5943 }
5944
5945 /* find the target table for 'store response' rules */
5946 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5947 struct proxy *target;
5948
Emeric Brun1d33b292010-01-04 15:47:17 +01005949 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5950
Emeric Brunb982a3d2010-01-04 15:45:53 +01005951 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005952 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005953 else
5954 target = curproxy;
5955
5956 if (!target) {
5957 Alert("Proxy '%s': unable to find store table '%s'.\n",
5958 curproxy->id, mrule->table.name);
5959 cfgerr++;
5960 }
5961 else if (target->table.size == 0) {
5962 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5963 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5964 cfgerr++;
5965 }
Willy Tarreau12785782012-04-27 21:37:17 +02005966 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5967 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005968 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5969 cfgerr++;
5970 }
5971 else {
5972 free((void *)mrule->table.name);
5973 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005974 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005975 }
5976 }
5977
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005978 /* find the target table for 'tcp-request' layer 4 rules */
5979 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5980 struct proxy *target;
5981
Willy Tarreau56123282010-08-06 19:06:56 +02005982 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005983 continue;
5984
5985 if (trule->act_prm.trk_ctr.table.n)
5986 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5987 else
5988 target = curproxy;
5989
5990 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005991 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5992 curproxy->id, trule->act_prm.trk_ctr.table.n,
5993 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005994 cfgerr++;
5995 }
5996 else if (target->table.size == 0) {
5997 Alert("Proxy '%s': table '%s' used but not configured.\n",
5998 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5999 cfgerr++;
6000 }
6001 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006002 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 +02006003 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6004 cfgerr++;
6005 }
6006 else {
6007 free(trule->act_prm.trk_ctr.table.n);
6008 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006009 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006010 * to pass a list of counters to track and allocate them right here using
6011 * stktable_alloc_data_type().
6012 */
6013 }
6014 }
6015
Willy Tarreaud1f96522010-08-03 19:34:32 +02006016 /* find the target table for 'tcp-request' layer 6 rules */
6017 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6018 struct proxy *target;
6019
Willy Tarreau56123282010-08-06 19:06:56 +02006020 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006021 continue;
6022
6023 if (trule->act_prm.trk_ctr.table.n)
6024 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6025 else
6026 target = curproxy;
6027
6028 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006029 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6030 curproxy->id, trule->act_prm.trk_ctr.table.n,
6031 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006032 cfgerr++;
6033 }
6034 else if (target->table.size == 0) {
6035 Alert("Proxy '%s': table '%s' used but not configured.\n",
6036 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6037 cfgerr++;
6038 }
6039 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006040 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 +02006041 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6042 cfgerr++;
6043 }
6044 else {
6045 free(trule->act_prm.trk_ctr.table.n);
6046 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006047 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006048 * to pass a list of counters to track and allocate them right here using
6049 * stktable_alloc_data_type().
6050 */
6051 }
6052 }
6053
Emeric Brun32da3c42010-09-23 18:39:19 +02006054 if (curproxy->table.peers.name) {
6055 struct peers *curpeers = peers;
6056
6057 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6058 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6059 free((void *)curproxy->table.peers.name);
6060 curproxy->table.peers.p = peers;
6061 break;
6062 }
6063 }
6064
6065 if (!curpeers) {
6066 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6067 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006068 free((void *)curproxy->table.peers.name);
6069 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006070 cfgerr++;
6071 }
6072 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006073 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6074 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006075 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006076 cfgerr++;
6077 }
6078 }
6079
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006080 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006081 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006082 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6083 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6084 "proxy", curproxy->id);
6085 cfgerr++;
6086 goto out_uri_auth_compat;
6087 }
6088
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006089 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006090 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006091 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006092 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006093
Willy Tarreau95fa4692010-02-01 13:05:50 +01006094 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6095 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006096
6097 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006098 uri_auth_compat_req[i++] = "realm";
6099 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6100 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006101
Willy Tarreau95fa4692010-02-01 13:05:50 +01006102 uri_auth_compat_req[i++] = "unless";
6103 uri_auth_compat_req[i++] = "{";
6104 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6105 uri_auth_compat_req[i++] = "}";
6106 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006107
Willy Tarreauff011f22011-01-06 17:51:27 +01006108 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6109 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006110 cfgerr++;
6111 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006112 }
6113
Willy Tarreauff011f22011-01-06 17:51:27 +01006114 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006115
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006116 if (curproxy->uri_auth->auth_realm) {
6117 free(curproxy->uri_auth->auth_realm);
6118 curproxy->uri_auth->auth_realm = NULL;
6119 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006120
6121 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006122 }
6123out_uri_auth_compat:
6124
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006125 cfgerr += acl_find_targets(curproxy);
6126
Willy Tarreau2738a142006-07-08 17:28:09 +02006127 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006128 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006129 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006130 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006131 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006132 " | While not properly invalid, you will certainly encounter various problems\n"
6133 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006134 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006135 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006136 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006137 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006138
Willy Tarreau1fa31262007-12-03 00:36:16 +01006139 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6140 * We must still support older configurations, so let's find out whether those
6141 * parameters have been set or must be copied from contimeouts.
6142 */
6143 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006144 if (!curproxy->timeout.tarpit ||
6145 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006146 /* tarpit timeout not set. We search in the following order:
6147 * default.tarpit, curr.connect, default.connect.
6148 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006149 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006150 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006151 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006152 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006153 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006154 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006155 }
6156 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006157 (!curproxy->timeout.queue ||
6158 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006159 /* queue timeout not set. We search in the following order:
6160 * default.queue, curr.connect, default.connect.
6161 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006162 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006163 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006164 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006165 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006166 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006167 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006168 }
6169 }
6170
Willy Tarreau1620ec32011-08-06 17:05:02 +02006171 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006172 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6173 curproxy->check_req = (char *)malloc(curproxy->check_len);
6174 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006175 }
6176
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006177 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006178 if (curproxy->nb_req_cap) {
6179 if (curproxy->mode == PR_MODE_HTTP) {
6180 curproxy->req_cap_pool = create_pool("ptrcap",
6181 curproxy->nb_req_cap * sizeof(char *),
6182 MEM_F_SHARED);
6183 } else {
6184 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6185 proxy_type_str(curproxy), curproxy->id);
6186 err_code |= ERR_WARN;
6187 curproxy->to_log &= ~LW_REQHDR;
6188 curproxy->nb_req_cap = 0;
6189 }
6190 }
6191
6192 if (curproxy->nb_rsp_cap) {
6193 if (curproxy->mode == PR_MODE_HTTP) {
6194 curproxy->rsp_cap_pool = create_pool("ptrcap",
6195 curproxy->nb_rsp_cap * sizeof(char *),
6196 MEM_F_SHARED);
6197 } else {
6198 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6199 proxy_type_str(curproxy), curproxy->id);
6200 err_code |= ERR_WARN;
6201 curproxy->to_log &= ~LW_REQHDR;
6202 curproxy->nb_rsp_cap = 0;
6203 }
6204 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006205
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206 /* first, we will invert the servers list order */
6207 newsrv = NULL;
6208 while (curproxy->srv) {
6209 struct server *next;
6210
6211 next = curproxy->srv->next;
6212 curproxy->srv->next = newsrv;
6213 newsrv = curproxy->srv;
6214 if (!next)
6215 break;
6216 curproxy->srv = next;
6217 }
6218
Willy Tarreaudd701652010-05-25 23:03:02 +02006219 /* assign automatic UIDs to servers which don't have one yet */
6220 next_id = 1;
6221 newsrv = curproxy->srv;
6222 while (newsrv != NULL) {
6223 if (!newsrv->puid) {
6224 /* server ID not set, use automatic numbering with first
6225 * spare entry starting with next_svid.
6226 */
6227 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6228 newsrv->conf.id.key = newsrv->puid = next_id;
6229 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6230 }
6231 next_id++;
6232 newsrv = newsrv->next;
6233 }
6234
Willy Tarreau20697042007-11-15 23:26:18 +01006235 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006236 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237
Willy Tarreau62c3be22012-01-20 13:12:32 +01006238 /*
6239 * If this server supports a maxconn parameter, it needs a dedicated
6240 * tasks to fill the emptied slots when a connection leaves.
6241 * Also, resolve deferred tracking dependency if needed.
6242 */
6243 newsrv = curproxy->srv;
6244 while (newsrv != NULL) {
6245 if (newsrv->minconn > newsrv->maxconn) {
6246 /* Only 'minconn' was specified, or it was higher than or equal
6247 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6248 * this will avoid further useless expensive computations.
6249 */
6250 newsrv->maxconn = newsrv->minconn;
6251 } else if (newsrv->maxconn && !newsrv->minconn) {
6252 /* minconn was not specified, so we set it to maxconn */
6253 newsrv->minconn = newsrv->maxconn;
6254 }
6255
6256 if (newsrv->trackit) {
6257 struct proxy *px;
6258 struct server *srv;
6259 char *pname, *sname;
6260
6261 pname = newsrv->trackit;
6262 sname = strrchr(pname, '/');
6263
6264 if (sname)
6265 *sname++ = '\0';
6266 else {
6267 sname = pname;
6268 pname = NULL;
6269 }
6270
6271 if (pname) {
6272 px = findproxy(pname, PR_CAP_BE);
6273 if (!px) {
6274 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6275 proxy_type_str(curproxy), curproxy->id,
6276 newsrv->id, pname);
6277 cfgerr++;
6278 goto next_srv;
6279 }
6280 } else
6281 px = curproxy;
6282
6283 srv = findserver(px, sname);
6284 if (!srv) {
6285 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6286 proxy_type_str(curproxy), curproxy->id,
6287 newsrv->id, sname);
6288 cfgerr++;
6289 goto next_srv;
6290 }
6291
6292 if (!(srv->state & SRV_CHECKED)) {
6293 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6294 "tracking as it does not have checks enabled.\n",
6295 proxy_type_str(curproxy), curproxy->id,
6296 newsrv->id, px->id, srv->id);
6297 cfgerr++;
6298 goto next_srv;
6299 }
6300
6301 if (curproxy != px &&
6302 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6303 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6304 "tracking: disable-on-404 option inconsistency.\n",
6305 proxy_type_str(curproxy), curproxy->id,
6306 newsrv->id, px->id, srv->id);
6307 cfgerr++;
6308 goto next_srv;
6309 }
6310
6311 /* if the other server is forced disabled, we have to do the same here */
6312 if (srv->state & SRV_MAINTAIN) {
6313 newsrv->state |= SRV_MAINTAIN;
6314 newsrv->state &= ~SRV_RUNNING;
6315 newsrv->health = 0;
6316 }
6317
6318 newsrv->track = srv;
6319 newsrv->tracknext = srv->tracknext;
6320 srv->tracknext = newsrv;
6321
6322 free(newsrv->trackit);
6323 newsrv->trackit = NULL;
6324 }
6325 next_srv:
6326 newsrv = newsrv->next;
6327 }
6328
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006329 /* We have to initialize the server lookup mechanism depending
6330 * on what LB algorithm was choosen.
6331 */
6332
6333 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6334 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6335 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006336 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6337 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6338 init_server_map(curproxy);
6339 } else {
6340 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6341 fwrr_init_server_groups(curproxy);
6342 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006343 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006344
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006345 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006346 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6347 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6348 fwlc_init_server_tree(curproxy);
6349 } else {
6350 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6351 fas_init_server_tree(curproxy);
6352 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006353 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006354
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006355 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006356 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6357 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6358 chash_init_server_tree(curproxy);
6359 } else {
6360 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6361 init_server_map(curproxy);
6362 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006363 break;
6364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365
6366 if (curproxy->options & PR_O_LOGASAP)
6367 curproxy->to_log &= ~LW_BYTES;
6368
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006369 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006370 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006371 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6372 proxy_type_str(curproxy), curproxy->id);
6373 err_code |= ERR_WARN;
6374 }
6375
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006376 if (curproxy->mode != PR_MODE_HTTP) {
6377 int optnum;
6378
6379 if (curproxy->options & PR_O_COOK_ANY) {
6380 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6381 proxy_type_str(curproxy), curproxy->id);
6382 err_code |= ERR_WARN;
6383 }
6384
6385 if (curproxy->uri_auth) {
6386 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6387 proxy_type_str(curproxy), curproxy->id);
6388 err_code |= ERR_WARN;
6389 curproxy->uri_auth = NULL;
6390 }
6391
Willy Tarreau87cf5142011-08-19 22:57:24 +02006392 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006393 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6394 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6395 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006396 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006397 }
6398
6399 if (curproxy->options & PR_O_ORGTO) {
6400 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6401 "originalto", proxy_type_str(curproxy), curproxy->id);
6402 err_code |= ERR_WARN;
6403 curproxy->options &= ~PR_O_ORGTO;
6404 }
6405
6406 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6407 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6408 (curproxy->cap & cfg_opts[optnum].cap) &&
6409 (curproxy->options & cfg_opts[optnum].val)) {
6410 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6411 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6412 err_code |= ERR_WARN;
6413 curproxy->options &= ~cfg_opts[optnum].val;
6414 }
6415 }
6416
6417 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6418 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6419 (curproxy->cap & cfg_opts2[optnum].cap) &&
6420 (curproxy->options2 & cfg_opts2[optnum].val)) {
6421 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6422 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6423 err_code |= ERR_WARN;
6424 curproxy->options2 &= ~cfg_opts2[optnum].val;
6425 }
6426 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006427
Willy Tarreauefa5f512010-03-30 20:13:29 +02006428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006429 if (curproxy->bind_hdr_occ) {
6430 curproxy->bind_hdr_occ = 0;
6431 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6432 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6433 err_code |= ERR_WARN;
6434 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006435#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006436 }
6437
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006439 * ensure that we're not cross-dressing a TCP server into HTTP.
6440 */
6441 newsrv = curproxy->srv;
6442 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006443 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6445 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006446 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006447 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006448
Willy Tarreau0cec3312011-10-31 13:49:26 +01006449 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6450 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6451 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6452 err_code |= ERR_WARN;
6453 }
6454
Willy Tarreauefa5f512010-03-30 20:13:29 +02006455#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006456 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6457 newsrv->bind_hdr_occ = 0;
6458 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6459 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6460 err_code |= ERR_WARN;
6461 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006462#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006463 newsrv = newsrv->next;
6464 }
6465
Willy Tarreauc1a21672009-08-16 22:37:44 +02006466 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006467 curproxy->accept = frontend_accept;
6468
Willy Tarreauc1a21672009-08-16 22:37:44 +02006469 if (curproxy->tcp_req.inspect_delay ||
6470 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006471 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006472
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006473 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006474 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006475 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006476 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006477
6478 /* both TCP and HTTP must check switching rules */
6479 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6480 }
6481
6482 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006483 if (curproxy->tcp_req.inspect_delay ||
6484 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6485 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6486
Emeric Brun97679e72010-09-23 17:56:44 +02006487 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6488 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6489
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006490 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006491 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006492 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006493 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006494
6495 /* If the backend does requires RDP cookie persistence, we have to
6496 * enable the corresponding analyser.
6497 */
6498 if (curproxy->options2 & PR_O2_RDPC_PRST)
6499 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6500 }
6501
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006502 listener = NULL;
6503 while (curproxy->listen) {
6504 struct listener *next;
6505
6506 next = curproxy->listen->next;
6507 curproxy->listen->next = listener;
6508 listener = curproxy->listen;
6509
6510 if (!next)
6511 break;
6512
6513 curproxy->listen = next;
6514 }
6515
Willy Tarreaue6b98942007-10-29 01:09:36 +01006516 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006517 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006518 listener = curproxy->listen;
6519 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006520 if (!listener->luid) {
6521 /* listener ID not set, use automatic numbering with first
6522 * spare entry starting with next_luid.
6523 */
6524 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6525 listener->conf.id.key = listener->luid = next_id;
6526 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006527 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006528 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006529
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006530 /* enable separate counters */
6531 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6532 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6533 if (!listener->name) {
6534 sprintf(trash, "sock-%d", listener->luid);
6535 listener->name = strdup(trash);
6536 }
6537 }
6538
Willy Tarreaue6b98942007-10-29 01:09:36 +01006539 if (curproxy->options & PR_O_TCP_NOLING)
6540 listener->options |= LI_O_NOLINGER;
6541 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006542 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006543 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006544 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006545 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006546 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006547 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006548
Willy Tarreau8a956912010-10-15 14:27:08 +02006549 if (listener->options & LI_O_ACC_PROXY)
6550 listener->analysers |= AN_REQ_DECODE_PROXY;
6551
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006552 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6553 listener->options |= LI_O_TCP_RULES;
6554
Willy Tarreaude3041d2010-05-31 10:56:17 +02006555 if (curproxy->mon_mask.s_addr)
6556 listener->options |= LI_O_CHK_MONNET;
6557
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006558 /* smart accept mode is automatic in HTTP mode */
6559 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6560 (curproxy->mode == PR_MODE_HTTP &&
6561 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6562 listener->options |= LI_O_NOQUICKACK;
6563
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006564 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006565 listener = listener->next;
6566 }
6567
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006568 /* Check multi-process mode compatibility for the current proxy */
6569 if (global.nbproc > 1) {
6570 int nbproc = 0;
6571 if (curproxy->bind_proc) {
6572 int proc;
6573 for (proc = 0; proc < global.nbproc; proc++) {
6574 if (curproxy->bind_proc & (1 << proc)) {
6575 nbproc++;
6576 }
6577 }
6578 } else {
6579 nbproc = global.nbproc;
6580 }
6581 if (curproxy->table.peers.name) {
6582 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6583 curproxy->id);
6584 cfgerr++;
6585 }
6586 if (nbproc > 1) {
6587 if (curproxy->uri_auth) {
6588 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6589 curproxy->id);
6590 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6591 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6592 curproxy->id);
6593 }
6594 }
6595 if (curproxy->appsession_name) {
6596 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6597 curproxy->id);
6598 }
6599 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6600 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6601 curproxy->id);
6602 }
6603 }
6604 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006605
6606 /* create the task associated with the proxy */
6607 curproxy->task = task_new();
6608 if (curproxy->task) {
6609 curproxy->task->context = curproxy;
6610 curproxy->task->process = manage_proxy;
6611 /* no need to queue, it will be done automatically if some
6612 * listener gets limited.
6613 */
6614 curproxy->task->expire = TICK_ETERNITY;
6615 } else {
6616 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6617 curproxy->id);
6618 cfgerr++;
6619 }
6620
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621 curproxy = curproxy->next;
6622 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006623
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006624 /* Check multi-process mode compatibility */
6625 if (global.nbproc > 1) {
6626 if (global.stats_fe) {
6627 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6628 }
6629 }
6630
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006631 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6632 struct auth_users *curuser;
6633 int g;
6634
6635 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6636 unsigned int group_mask = 0;
6637 char *group = NULL;
6638
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006639 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006640 continue;
6641
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006642 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006643
6644 for (g = 0; g < curuserlist->grpcnt; g++)
6645 if (!strcmp(curuserlist->groups[g], group))
6646 break;
6647
6648 if (g == curuserlist->grpcnt) {
6649 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6650 curuserlist->name, group, curuser->user);
6651 err_code |= ERR_ALERT | ERR_FATAL;
6652 goto out;
6653 }
6654
6655 group_mask |= (1 << g);
6656 }
6657
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006658 free(curuser->u.groups);
6659 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006660 }
6661
6662 for (g = 0; g < curuserlist->grpcnt; g++) {
6663 char *user = NULL;
6664
6665 if (!curuserlist->groupusers[g])
6666 continue;
6667
6668 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6669 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6670 if (!strcmp(curuser->user, user))
6671 break;
6672
6673 if (!curuser) {
6674 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6675 curuserlist->name, user, curuserlist->groups[g]);
6676 err_code |= ERR_ALERT | ERR_FATAL;
6677 goto out;
6678 }
6679
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006680 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006681 }
6682
6683 free(curuserlist->groupusers[g]);
6684 }
6685
6686 free(curuserlist->groupusers);
6687
6688#ifdef DEBUG_AUTH
6689 for (g = 0; g < curuserlist->grpcnt; g++) {
6690 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6691
6692 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006693 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006694 fprintf(stderr, " %s", curuser->user);
6695 }
6696
6697 fprintf(stderr, "\n");
6698 }
6699#endif
6700
Willy Tarreaufbb78422011-06-05 15:38:35 +02006701 }
6702
6703 /* automatically compute fullconn if not set. We must not do it in the
6704 * loop above because cross-references are not yet fully resolved.
6705 */
6706 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6707 /* If <fullconn> is not set, let's set it to 10% of the sum of
6708 * the possible incoming frontend's maxconns.
6709 */
6710 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6711 struct proxy *fe;
6712 int total = 0;
6713
6714 /* sum up the number of maxconns of frontends which
6715 * reference this backend at least once or which are
6716 * the same one ('listen').
6717 */
6718 for (fe = proxy; fe; fe = fe->next) {
6719 struct switching_rule *rule;
6720 struct hdr_exp *exp;
6721 int found = 0;
6722
6723 if (!(fe->cap & PR_CAP_FE))
6724 continue;
6725
6726 if (fe == curproxy) /* we're on a "listen" instance */
6727 found = 1;
6728
6729 if (fe->defbe.be == curproxy) /* "default_backend" */
6730 found = 1;
6731
6732 /* check if a "use_backend" rule matches */
6733 if (!found) {
6734 list_for_each_entry(rule, &fe->switching_rules, list) {
6735 if (rule->be.backend == curproxy) {
6736 found = 1;
6737 break;
6738 }
6739 }
6740 }
6741
6742 /* check if a "reqsetbe" rule matches */
6743 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6744 if (exp->action == ACT_SETBE &&
6745 (struct proxy *)exp->replace == curproxy) {
6746 found = 1;
6747 break;
6748 }
6749 }
6750
6751 /* now we've checked all possible ways to reference a backend
6752 * from a frontend.
6753 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006754 if (!found)
6755 continue;
6756 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006757 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006758 /* we have the sum of the maxconns in <total>. We only
6759 * keep 10% of that sum to set the default fullconn, with
6760 * a hard minimum of 1 (to avoid a divide by zero).
6761 */
6762 curproxy->fullconn = (total + 9) / 10;
6763 if (!curproxy->fullconn)
6764 curproxy->fullconn = 1;
6765 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006766 }
6767
Willy Tarreau056f5682010-06-06 15:51:11 +02006768 /* initialize stick-tables on backend capable proxies. This must not
6769 * be done earlier because the data size may be discovered while parsing
6770 * other proxies.
6771 */
6772 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006773 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006774
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006775 /*
6776 * Recount currently required checks.
6777 */
6778
6779 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6780 int optnum;
6781
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006782 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6783 if (curproxy->options & cfg_opts[optnum].val)
6784 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006785
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006786 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6787 if (curproxy->options2 & cfg_opts2[optnum].val)
6788 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006789 }
6790
Willy Tarreau122541c2011-09-07 21:24:49 +02006791 if (peers) {
6792 struct peers *curpeers = peers, **last;
6793 struct peer *p, *pb;
6794
6795 /* Remove all peers sections which don't have a valid listener.
6796 * This can happen when a peers section is never referenced and
6797 * does not contain a local peer.
6798 */
6799 last = &peers;
6800 while (*last) {
6801 curpeers = *last;
6802 if (curpeers->peers_fe) {
6803 last = &curpeers->next;
6804 continue;
6805 }
6806
6807 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6808 curpeers->id, localpeer);
6809
6810 p = curpeers->remote;
6811 while (p) {
6812 pb = p->next;
6813 free(p->id);
6814 free(p);
6815 p = pb;
6816 }
6817
6818 /* Destroy and unlink this curpeers section.
6819 * Note: curpeers is backed up into *last.
6820 */
6821 free(curpeers->id);
6822 curpeers = curpeers->next;
6823 free(*last);
6824 *last = curpeers;
6825 }
6826 }
6827
Willy Tarreauac1932d2011-10-24 19:14:41 +02006828 if (!global.tune.max_http_hdr)
6829 global.tune.max_http_hdr = MAX_HTTP_HDR;
6830
Willy Tarreau34eb6712011-10-24 18:15:04 +02006831 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006832 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006833 MEM_F_SHARED);
6834
Willy Tarreaubb925012009-07-23 13:36:36 +02006835 if (cfgerr > 0)
6836 err_code |= ERR_ALERT | ERR_FATAL;
6837 out:
6838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839}
6840
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006841/*
6842 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6843 * parsing sessions.
6844 */
6845void cfg_register_keywords(struct cfg_kw_list *kwl)
6846{
6847 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6848}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006850/*
6851 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6852 */
6853void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6854{
6855 LIST_DEL(&kwl->list);
6856 LIST_INIT(&kwl->list);
6857}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006858
6859/*
6860 * Local variables:
6861 * c-indent-level: 8
6862 * c-basic-offset: 8
6863 * End:
6864 */